]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 10 Oct 2013 23:57:20 +0000 (16:57 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 10 Oct 2013 23:57:20 +0000 (16:57 -0700)
added patches:
acpi-ipmi-fix-atomic-context-requirement-of-ipmi_msg_handler.patch
btrfs-change-how-we-queue-blocks-for-backref-checking.patch
ext4-avoid-hang-when-mounting-non-journal-filesystems-with-orphan-list.patch
mm-show_mem-suppress-page-counts-in-non-blockable-contexts.patch
tile-use-a-more-conservative-__my_cpu_offset-in-config_preempt.patch

queue-3.4/acpi-ipmi-fix-atomic-context-requirement-of-ipmi_msg_handler.patch [new file with mode: 0644]
queue-3.4/btrfs-change-how-we-queue-blocks-for-backref-checking.patch [new file with mode: 0644]
queue-3.4/ext4-avoid-hang-when-mounting-non-journal-filesystems-with-orphan-list.patch [new file with mode: 0644]
queue-3.4/mm-show_mem-suppress-page-counts-in-non-blockable-contexts.patch [new file with mode: 0644]
queue-3.4/series
queue-3.4/tile-use-a-more-conservative-__my_cpu_offset-in-config_preempt.patch [new file with mode: 0644]

diff --git a/queue-3.4/acpi-ipmi-fix-atomic-context-requirement-of-ipmi_msg_handler.patch b/queue-3.4/acpi-ipmi-fix-atomic-context-requirement-of-ipmi_msg_handler.patch
new file mode 100644 (file)
index 0000000..325d2f3
--- /dev/null
@@ -0,0 +1,181 @@
+From 06a8566bcf5cf7db9843a82cde7a33c7bf3947d9 Mon Sep 17 00:00:00 2001
+From: Lv Zheng <lv.zheng@intel.com>
+Date: Fri, 13 Sep 2013 13:13:23 +0800
+Subject: ACPI / IPMI: Fix atomic context requirement of ipmi_msg_handler()
+
+From: Lv Zheng <lv.zheng@intel.com>
+
+commit 06a8566bcf5cf7db9843a82cde7a33c7bf3947d9 upstream.
+
+This patch fixes the issues indicated by the test results that
+ipmi_msg_handler() is invoked in atomic context.
+
+BUG: scheduling while atomic: kipmi0/18933/0x10000100
+Modules linked in: ipmi_si acpi_ipmi ...
+CPU: 3 PID: 18933 Comm: kipmi0 Tainted: G       AW    3.10.0-rc7+ #2
+Hardware name: QCI QSSC-S4R/QSSC-S4R, BIOS QSSC-S4R.QCI.01.00.0027.070120100606 07/01/2010
+ ffff8838245eea00 ffff88103fc63c98 ffffffff814c4a1e ffff88103fc63ca8
+ ffffffff814bfbab ffff88103fc63d28 ffffffff814c73e0 ffff88103933cbd4
+ 0000000000000096 ffff88103fc63ce8 ffff88102f618000 ffff881035c01fd8
+Call Trace:
+ <IRQ>  [<ffffffff814c4a1e>] dump_stack+0x19/0x1b
+ [<ffffffff814bfbab>] __schedule_bug+0x46/0x54
+ [<ffffffff814c73e0>] __schedule+0x83/0x59c
+ [<ffffffff81058853>] __cond_resched+0x22/0x2d
+ [<ffffffff814c794b>] _cond_resched+0x14/0x1d
+ [<ffffffff814c6d82>] mutex_lock+0x11/0x32
+ [<ffffffff8101e1e9>] ? __default_send_IPI_dest_field.constprop.0+0x53/0x58
+ [<ffffffffa09e3f9c>] ipmi_msg_handler+0x23/0x166 [ipmi_si]
+ [<ffffffff812bf6e4>] deliver_response+0x55/0x5a
+ [<ffffffff812c0fd4>] handle_new_recv_msgs+0xb67/0xc65
+ [<ffffffff81007ad1>] ? read_tsc+0x9/0x19
+ [<ffffffff814c8620>] ? _raw_spin_lock_irq+0xa/0xc
+ [<ffffffffa09e1128>] ipmi_thread+0x5c/0x146 [ipmi_si]
+ ...
+
+Also Tony Camuso says:
+
+ We were getting occasional "Scheduling while atomic" call traces
+ during boot on some systems. Problem was first seen on a Cisco C210
+ but we were able to reproduce it on a Cisco c220m3. Setting
+ CONFIG_LOCKDEP and LOCKDEP_SUPPORT to 'y' exposed a lockdep around
+ tx_msg_lock in acpi_ipmi.c struct acpi_ipmi_device.
+
+ =================================
+ [ INFO: inconsistent lock state ]
+ 2.6.32-415.el6.x86_64-debug-splck #1
+ ---------------------------------
+ inconsistent {SOFTIRQ-ON-W} -> {IN-SOFTIRQ-W} usage.
+ ksoftirqd/3/17 [HC0[0]:SC1[1]:HE1:SE0] takes:
+  (&ipmi_device->tx_msg_lock){+.?...}, at: [<ffffffff81337a27>] ipmi_msg_handler+0x71/0x126
+ {SOFTIRQ-ON-W} state was registered at:
+   [<ffffffff810ba11c>] __lock_acquire+0x63c/0x1570
+   [<ffffffff810bb0f4>] lock_acquire+0xa4/0x120
+   [<ffffffff815581cc>] __mutex_lock_common+0x4c/0x400
+   [<ffffffff815586ea>] mutex_lock_nested+0x4a/0x60
+   [<ffffffff8133789d>] acpi_ipmi_space_handler+0x11b/0x234
+   [<ffffffff81321c62>] acpi_ev_address_space_dispatch+0x170/0x1be
+
+The fix implemented by this change has been tested by Tony:
+
+ Tested the patch in a boot loop with lockdep debug enabled and never
+ saw the problem in over 400 reboots.
+
+Reported-and-tested-by: Tony Camuso <tcamuso@redhat.com>
+Signed-off-by: Lv Zheng <lv.zheng@intel.com>
+Reviewed-by: Huang Ying <ying.huang@intel.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Cc: Jonghwan Choi <jhbird.choi@samsung.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/acpi/acpi_ipmi.c |   24 ++++++++++++++----------
+ 1 file changed, 14 insertions(+), 10 deletions(-)
+
+--- a/drivers/acpi/acpi_ipmi.c
++++ b/drivers/acpi/acpi_ipmi.c
+@@ -39,6 +39,7 @@
+ #include <linux/ipmi.h>
+ #include <linux/device.h>
+ #include <linux/pnp.h>
++#include <linux/spinlock.h>
+ MODULE_AUTHOR("Zhao Yakui");
+ MODULE_DESCRIPTION("ACPI IPMI Opregion driver");
+@@ -57,7 +58,7 @@ struct acpi_ipmi_device {
+       struct list_head head;
+       /* the IPMI request message list */
+       struct list_head tx_msg_list;
+-      struct mutex    tx_msg_lock;
++      spinlock_t      tx_msg_lock;
+       acpi_handle handle;
+       struct pnp_dev *pnp_dev;
+       ipmi_user_t     user_interface;
+@@ -147,6 +148,7 @@ static void acpi_format_ipmi_msg(struct
+       struct kernel_ipmi_msg *msg;
+       struct acpi_ipmi_buffer *buffer;
+       struct acpi_ipmi_device *device;
++      unsigned long flags;
+       msg = &tx_msg->tx_message;
+       /*
+@@ -177,10 +179,10 @@ static void acpi_format_ipmi_msg(struct
+       /* Get the msgid */
+       device = tx_msg->device;
+-      mutex_lock(&device->tx_msg_lock);
++      spin_lock_irqsave(&device->tx_msg_lock, flags);
+       device->curr_msgid++;
+       tx_msg->tx_msgid = device->curr_msgid;
+-      mutex_unlock(&device->tx_msg_lock);
++      spin_unlock_irqrestore(&device->tx_msg_lock, flags);
+ }
+ static void acpi_format_ipmi_response(struct acpi_ipmi_msg *msg,
+@@ -242,6 +244,7 @@ static void ipmi_msg_handler(struct ipmi
+       int msg_found = 0;
+       struct acpi_ipmi_msg *tx_msg;
+       struct pnp_dev *pnp_dev = ipmi_device->pnp_dev;
++      unsigned long flags;
+       if (msg->user != ipmi_device->user_interface) {
+               dev_warn(&pnp_dev->dev, "Unexpected response is returned. "
+@@ -250,7 +253,7 @@ static void ipmi_msg_handler(struct ipmi
+               ipmi_free_recv_msg(msg);
+               return;
+       }
+-      mutex_lock(&ipmi_device->tx_msg_lock);
++      spin_lock_irqsave(&ipmi_device->tx_msg_lock, flags);
+       list_for_each_entry(tx_msg, &ipmi_device->tx_msg_list, head) {
+               if (msg->msgid == tx_msg->tx_msgid) {
+                       msg_found = 1;
+@@ -258,7 +261,7 @@ static void ipmi_msg_handler(struct ipmi
+               }
+       }
+-      mutex_unlock(&ipmi_device->tx_msg_lock);
++      spin_unlock_irqrestore(&ipmi_device->tx_msg_lock, flags);
+       if (!msg_found) {
+               dev_warn(&pnp_dev->dev, "Unexpected response (msg id %ld) is "
+                       "returned.\n", msg->msgid);
+@@ -378,6 +381,7 @@ acpi_ipmi_space_handler(u32 function, ac
+       struct acpi_ipmi_device *ipmi_device = handler_context;
+       int err, rem_time;
+       acpi_status status;
++      unsigned long flags;
+       /*
+        * IPMI opregion message.
+        * IPMI message is firstly written to the BMC and system software
+@@ -395,9 +399,9 @@ acpi_ipmi_space_handler(u32 function, ac
+               return AE_NO_MEMORY;
+       acpi_format_ipmi_msg(tx_msg, address, value);
+-      mutex_lock(&ipmi_device->tx_msg_lock);
++      spin_lock_irqsave(&ipmi_device->tx_msg_lock, flags);
+       list_add_tail(&tx_msg->head, &ipmi_device->tx_msg_list);
+-      mutex_unlock(&ipmi_device->tx_msg_lock);
++      spin_unlock_irqrestore(&ipmi_device->tx_msg_lock, flags);
+       err = ipmi_request_settime(ipmi_device->user_interface,
+                                       &tx_msg->addr,
+                                       tx_msg->tx_msgid,
+@@ -413,9 +417,9 @@ acpi_ipmi_space_handler(u32 function, ac
+       status = AE_OK;
+ end_label:
+-      mutex_lock(&ipmi_device->tx_msg_lock);
++      spin_lock_irqsave(&ipmi_device->tx_msg_lock, flags);
+       list_del(&tx_msg->head);
+-      mutex_unlock(&ipmi_device->tx_msg_lock);
++      spin_unlock_irqrestore(&ipmi_device->tx_msg_lock, flags);
+       kfree(tx_msg);
+       return status;
+ }
+@@ -457,7 +461,7 @@ static void acpi_add_ipmi_device(struct
+       INIT_LIST_HEAD(&ipmi_device->head);
+-      mutex_init(&ipmi_device->tx_msg_lock);
++      spin_lock_init(&ipmi_device->tx_msg_lock);
+       INIT_LIST_HEAD(&ipmi_device->tx_msg_list);
+       ipmi_install_space_handler(ipmi_device);
diff --git a/queue-3.4/btrfs-change-how-we-queue-blocks-for-backref-checking.patch b/queue-3.4/btrfs-change-how-we-queue-blocks-for-backref-checking.patch
new file mode 100644 (file)
index 0000000..1146ba3
--- /dev/null
@@ -0,0 +1,68 @@
+From b6c60c8018c4e9beb2f83fc82c09f9d033766571 Mon Sep 17 00:00:00 2001
+From: Josef Bacik <jbacik@fusionio.com>
+Date: Tue, 30 Jul 2013 16:30:30 -0400
+Subject: Btrfs: change how we queue blocks for backref checking
+
+From: Josef Bacik <jbacik@fusionio.com>
+
+commit b6c60c8018c4e9beb2f83fc82c09f9d033766571 upstream.
+
+Previously we only added blocks to the list to have their backrefs checked if
+the level of the block is right above the one we are searching for.  This is
+because we want to make sure we don't add the entire path up to the root to the
+lists to make sure we process things one at a time.  This assumes that if any
+blocks in the path to the root are going to be not checked (shared in other
+words) then they will be in the level right above the current block on up.  This
+isn't quite right though since we can have blocks higher up the list that are
+shared because they are attached to a reloc root.  But we won't add this block
+to be checked and then later on we will BUG_ON(!upper->checked).  So instead
+keep track of wether or not we've queued a block to be checked in this current
+search, and if we haven't go ahead and queue it to be checked.  This patch fixed
+the panic I was seeing where we BUG_ON(!upper->checked).  Thanks,
+
+Signed-off-by: Josef Bacik <jbacik@fusionio.com>
+Signed-off-by: Chris Mason <chris.mason@fusionio.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/relocation.c |   14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+--- a/fs/btrfs/relocation.c
++++ b/fs/btrfs/relocation.c
+@@ -684,6 +684,7 @@ struct backref_node *build_backref_tree(
+       int cowonly;
+       int ret;
+       int err = 0;
++      bool need_check = true;
+       path1 = btrfs_alloc_path();
+       path2 = btrfs_alloc_path();
+@@ -906,6 +907,7 @@ again:
+                       cur->bytenr);
+               lower = cur;
++              need_check = true;
+               for (; level < BTRFS_MAX_LEVEL; level++) {
+                       if (!path2->nodes[level]) {
+                               BUG_ON(btrfs_root_bytenr(&root->root_item) !=
+@@ -949,14 +951,12 @@ again:
+                               /*
+                                * add the block to pending list if we
+-                               * need check its backrefs. only block
+-                               * at 'cur->level + 1' is added to the
+-                               * tail of pending list. this guarantees
+-                               * we check backrefs from lower level
+-                               * blocks to upper level blocks.
++                               * need check its backrefs, we only do this once
++                               * while walking up a tree as we will catch
++                               * anything else later on.
+                                */
+-                              if (!upper->checked &&
+-                                  level == cur->level + 1) {
++                              if (!upper->checked && need_check) {
++                                      need_check = false;
+                                       list_add_tail(&edge->list[UPPER],
+                                                     &list);
+                               } else
diff --git a/queue-3.4/ext4-avoid-hang-when-mounting-non-journal-filesystems-with-orphan-list.patch b/queue-3.4/ext4-avoid-hang-when-mounting-non-journal-filesystems-with-orphan-list.patch
new file mode 100644 (file)
index 0000000..35f58f5
--- /dev/null
@@ -0,0 +1,48 @@
+From 0e9a9a1ad619e7e987815d20262d36a2f95717ca Mon Sep 17 00:00:00 2001
+From: Theodore Ts'o <tytso@mit.edu>
+Date: Thu, 27 Dec 2012 01:42:50 -0500
+Subject: ext4: avoid hang when mounting non-journal filesystems with orphan list
+
+From: Theodore Ts'o <tytso@mit.edu>
+
+commit 0e9a9a1ad619e7e987815d20262d36a2f95717ca upstream.
+
+When trying to mount a file system which does not contain a journal,
+but which does have a orphan list containing an inode which needs to
+be truncated, the mount call with hang forever in
+ext4_orphan_cleanup() because ext4_orphan_del() will return
+immediately without removing the inode from the orphan list, leading
+to an uninterruptible loop in kernel code which will busy out one of
+the CPU's on the system.
+
+This can be trivially reproduced by trying to mount the file system
+found in tests/f_orphan_extents_inode/image.gz from the e2fsprogs
+source tree.  If a malicious user were to put this on a USB stick, and
+mount it on a Linux desktop which has automatic mounts enabled, this
+could be considered a potential denial of service attack.  (Not a big
+deal in practice, but professional paranoids worry about such things,
+and have even been known to allocate CVE numbers for such problems.)
+
+-js: This is a fix for CVE-2013-2015.
+
+Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
+Reviewed-by: Zheng Liu <wenqing.lz@taobao.com>
+Acked-by: Jan Kara <jack@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ext4/namei.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -2054,7 +2054,8 @@ int ext4_orphan_del(handle_t *handle, st
+       int err = 0;
+       /* ext4_handle_valid() assumes a valid handle_t pointer */
+-      if (handle && !ext4_handle_valid(handle))
++      if (handle && !ext4_handle_valid(handle) &&
++          !(EXT4_SB(inode->i_sb)->s_mount_state & EXT4_ORPHAN_FS))
+               return 0;
+       mutex_lock(&EXT4_SB(inode->i_sb)->s_orphan_lock);
diff --git a/queue-3.4/mm-show_mem-suppress-page-counts-in-non-blockable-contexts.patch b/queue-3.4/mm-show_mem-suppress-page-counts-in-non-blockable-contexts.patch
new file mode 100644 (file)
index 0000000..a1498f9
--- /dev/null
@@ -0,0 +1,137 @@
+From 4b59e6c4730978679b414a8da61514a2518da512 Mon Sep 17 00:00:00 2001
+From: David Rientjes <rientjes@google.com>
+Date: Mon, 29 Apr 2013 15:06:11 -0700
+Subject: mm, show_mem: suppress page counts in non-blockable contexts
+
+From: David Rientjes <rientjes@google.com>
+
+commit 4b59e6c4730978679b414a8da61514a2518da512 upstream.
+
+On large systems with a lot of memory, walking all RAM to determine page
+types may take a half second or even more.
+
+In non-blockable contexts, the page allocator will emit a page allocation
+failure warning unless __GFP_NOWARN is specified.  In such contexts, irqs
+are typically disabled and such a lengthy delay may even result in NMI
+watchdog timeouts.
+
+To fix this, suppress the page walk in such contexts when printing the
+page allocation failure warning.
+
+Signed-off-by: David Rientjes <rientjes@google.com>
+Cc: Mel Gorman <mgorman@suse.de>
+Acked-by: Michal Hocko <mhocko@suse.cz>
+Cc: Dave Hansen <dave@linux.vnet.ibm.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Xishi Qiu <qiuxishi@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/arm/mm/init.c       |    3 +++
+ arch/ia64/mm/contig.c    |    2 ++
+ arch/ia64/mm/discontig.c |    2 ++
+ arch/parisc/mm/init.c    |    2 ++
+ arch/unicore32/mm/init.c |    3 +++
+ include/linux/mm.h       |    3 ++-
+ lib/show_mem.c           |    3 +++
+ mm/page_alloc.c          |    7 +++++++
+ 8 files changed, 24 insertions(+), 1 deletion(-)
+
+--- a/arch/arm/mm/init.c
++++ b/arch/arm/mm/init.c
+@@ -98,6 +98,9 @@ void show_mem(unsigned int filter)
+       printk("Mem-info:\n");
+       show_free_areas(filter);
++      if (filter & SHOW_MEM_FILTER_PAGE_COUNT)
++              return;
++
+       for_each_bank (i, mi) {
+               struct membank *bank = &mi->bank[i];
+               unsigned int pfn1, pfn2;
+--- a/arch/ia64/mm/contig.c
++++ b/arch/ia64/mm/contig.c
+@@ -47,6 +47,8 @@ void show_mem(unsigned int filter)
+       printk(KERN_INFO "Mem-info:\n");
+       show_free_areas(filter);
+       printk(KERN_INFO "Node memory in pages:\n");
++      if (filter & SHOW_MEM_FILTER_PAGE_COUNT)
++              return;
+       for_each_online_pgdat(pgdat) {
+               unsigned long present;
+               unsigned long flags;
+--- a/arch/ia64/mm/discontig.c
++++ b/arch/ia64/mm/discontig.c
+@@ -623,6 +623,8 @@ void show_mem(unsigned int filter)
+       printk(KERN_INFO "Mem-info:\n");
+       show_free_areas(filter);
++      if (filter & SHOW_MEM_FILTER_PAGE_COUNT)
++              return;
+       printk(KERN_INFO "Node memory in pages:\n");
+       for_each_online_pgdat(pgdat) {
+               unsigned long present;
+--- a/arch/parisc/mm/init.c
++++ b/arch/parisc/mm/init.c
+@@ -685,6 +685,8 @@ void show_mem(unsigned int filter)
+       printk(KERN_INFO "Mem-info:\n");
+       show_free_areas(filter);
++      if (filter & SHOW_MEM_FILTER_PAGE_COUNT)
++              return;
+ #ifndef CONFIG_DISCONTIGMEM
+       i = max_mapnr;
+       while (i-- > 0) {
+--- a/arch/unicore32/mm/init.c
++++ b/arch/unicore32/mm/init.c
+@@ -66,6 +66,9 @@ void show_mem(unsigned int filter)
+       printk(KERN_DEFAULT "Mem-info:\n");
+       show_free_areas(filter);
++      if (filter & SHOW_MEM_FILTER_PAGE_COUNT)
++              return;
++
+       for_each_bank(i, mi) {
+               struct membank *bank = &mi->bank[i];
+               unsigned int pfn1, pfn2;
+--- a/include/linux/mm.h
++++ b/include/linux/mm.h
+@@ -866,7 +866,8 @@ extern void pagefault_out_of_memory(void
+  * Flags passed to show_mem() and show_free_areas() to suppress output in
+  * various contexts.
+  */
+-#define SHOW_MEM_FILTER_NODES (0x0001u)       /* filter disallowed nodes */
++#define SHOW_MEM_FILTER_NODES         (0x0001u)       /* disallowed nodes */
++#define SHOW_MEM_FILTER_PAGE_COUNT    (0x0002u)       /* page type count */
+ extern void show_free_areas(unsigned int flags);
+ extern bool skip_free_areas_node(unsigned int flags, int nid);
+--- a/lib/show_mem.c
++++ b/lib/show_mem.c
+@@ -18,6 +18,9 @@ void show_mem(unsigned int filter)
+       printk("Mem-Info:\n");
+       show_free_areas(filter);
++      if (filter & SHOW_MEM_FILTER_PAGE_COUNT)
++              return;
++
+       for_each_online_pgdat(pgdat) {
+               unsigned long i, flags;
+--- a/mm/page_alloc.c
++++ b/mm/page_alloc.c
+@@ -1885,6 +1885,13 @@ void warn_alloc_failed(gfp_t gfp_mask, i
+               return;
+       /*
++       * Walking all memory to count page types is very expensive and should
++       * be inhibited in non-blockable contexts.
++       */
++      if (!(gfp_mask & __GFP_WAIT))
++              filter |= SHOW_MEM_FILTER_PAGE_COUNT;
++
++      /*
+        * This documents exceptions given to allocations in certain
+        * contexts that are allowed to allocate outside current's set
+        * of allowed nodes.
index 3037f5ced7ec88d84503d685075ca93578f86f97..0b157bd659b17be1e3992717efa618babd341a2a 100644 (file)
@@ -37,3 +37,8 @@ dmaengine-imx-dma-fix-lockdep-issue-between-irqhandler-and-tasklet.patch
 dmaengine-imx-dma-fix-callback-path-in-tasklet.patch
 dmaengine-imx-dma-fix-slow-path-issue-in-prep_dma_cyclic.patch
 staging-comedi-ni_65xx-bug-fix-confine-insn_bits-to-one-subdevice.patch
+mm-show_mem-suppress-page-counts-in-non-blockable-contexts.patch
+acpi-ipmi-fix-atomic-context-requirement-of-ipmi_msg_handler.patch
+tile-use-a-more-conservative-__my_cpu_offset-in-config_preempt.patch
+btrfs-change-how-we-queue-blocks-for-backref-checking.patch
+ext4-avoid-hang-when-mounting-non-journal-filesystems-with-orphan-list.patch
diff --git a/queue-3.4/tile-use-a-more-conservative-__my_cpu_offset-in-config_preempt.patch b/queue-3.4/tile-use-a-more-conservative-__my_cpu_offset-in-config_preempt.patch
new file mode 100644 (file)
index 0000000..64a75e1
--- /dev/null
@@ -0,0 +1,71 @@
+From f862eefec0b68e099a9fa58d3761ffb10bad97e1 Mon Sep 17 00:00:00 2001
+From: Chris Metcalf <cmetcalf@tilera.com>
+Date: Thu, 26 Sep 2013 13:24:53 -0400
+Subject: tile: use a more conservative __my_cpu_offset in CONFIG_PREEMPT
+
+From: Chris Metcalf <cmetcalf@tilera.com>
+
+commit f862eefec0b68e099a9fa58d3761ffb10bad97e1 upstream.
+
+It turns out the kernel relies on barrier() to force a reload of the
+percpu offset value.  Since we can't easily modify the definition of
+barrier() to include "tp" as an output register, we instead provide a
+definition of __my_cpu_offset as extended assembly that includes a fake
+stack read to hazard against barrier(), forcing gcc to know that it
+must reread "tp" and recompute anything based on "tp" after a barrier.
+
+This fixes observed hangs in the slub allocator when we are looping
+on a percpu cmpxchg_double.
+
+A similar fix for ARMv7 was made in June in change 509eb76ebf97.
+
+Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/tile/include/asm/percpu.h |   34 +++++++++++++++++++++++++++++++---
+ 1 file changed, 31 insertions(+), 3 deletions(-)
+
+--- a/arch/tile/include/asm/percpu.h
++++ b/arch/tile/include/asm/percpu.h
+@@ -15,9 +15,37 @@
+ #ifndef _ASM_TILE_PERCPU_H
+ #define _ASM_TILE_PERCPU_H
+-register unsigned long __my_cpu_offset __asm__("tp");
+-#define __my_cpu_offset __my_cpu_offset
+-#define set_my_cpu_offset(tp) (__my_cpu_offset = (tp))
++register unsigned long my_cpu_offset_reg asm("tp");
++
++#ifdef CONFIG_PREEMPT
++/*
++ * For full preemption, we can't just use the register variable
++ * directly, since we need barrier() to hazard against it, causing the
++ * compiler to reload anything computed from a previous "tp" value.
++ * But we also don't want to use volatile asm, since we'd like the
++ * compiler to be able to cache the value across multiple percpu reads.
++ * So we use a fake stack read as a hazard against barrier().
++ * The 'U' constraint is like 'm' but disallows postincrement.
++ */
++static inline unsigned long __my_cpu_offset(void)
++{
++      unsigned long tp;
++      register unsigned long *sp asm("sp");
++      asm("move %0, tp" : "=r" (tp) : "U" (*sp));
++      return tp;
++}
++#define __my_cpu_offset __my_cpu_offset()
++#else
++/*
++ * We don't need to hazard against barrier() since "tp" doesn't ever
++ * change with PREEMPT_NONE, and with PREEMPT_VOLUNTARY it only
++ * changes at function call points, at which we are already re-reading
++ * the value of "tp" due to "my_cpu_offset_reg" being a global variable.
++ */
++#define __my_cpu_offset my_cpu_offset_reg
++#endif
++
++#define set_my_cpu_offset(tp) (my_cpu_offset_reg = (tp))
+ #include <asm-generic/percpu.h>