]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 27 Sep 2012 00:13:53 +0000 (17:13 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 27 Sep 2012 00:13:53 +0000 (17:13 -0700)
added patches:
md-raid10-fix-problem-with-on-stack-allocation-of-r10bio-structure.patch
workqueue-unbound-rebind-morphing-in-rebind_workers-should-be-atomic.patch
x86-fix-boot-on-twinhead-h12y.patch

queue-3.4/md-raid10-fix-problem-with-on-stack-allocation-of-r10bio-structure.patch [new file with mode: 0644]
queue-3.4/series
queue-3.4/workqueue-unbound-rebind-morphing-in-rebind_workers-should-be-atomic.patch [new file with mode: 0644]
queue-3.4/x86-fix-boot-on-twinhead-h12y.patch [new file with mode: 0644]

diff --git a/queue-3.4/md-raid10-fix-problem-with-on-stack-allocation-of-r10bio-structure.patch b/queue-3.4/md-raid10-fix-problem-with-on-stack-allocation-of-r10bio-structure.patch
new file mode 100644 (file)
index 0000000..a5e1411
--- /dev/null
@@ -0,0 +1,87 @@
+From e0ee778528bbaad28a5c69d2e219269a3a096607 Mon Sep 17 00:00:00 2001
+From: NeilBrown <neilb@suse.de>
+Date: Sat, 18 Aug 2012 09:51:42 +1000
+Subject: md/raid10: fix problem with on-stack allocation of r10bio structure.
+
+From: NeilBrown <neilb@suse.de>
+
+commit e0ee778528bbaad28a5c69d2e219269a3a096607 upstream.
+
+A 'struct r10bio' has an array of per-copy information at the end.
+This array is declared with size [0] and r10bio_pool_alloc allocates
+enough extra space to store the per-copy information depending on the
+number of copies needed.
+
+So declaring a 'struct r10bio on the stack isn't going to work.  It
+won't allocate enough space, and memory corruption will ensue.
+
+So in the two places where this is done, declare a sufficiently large
+structure and use that instead.
+
+The two call-sites of this bug were introduced in 3.4 and 3.5
+so this is suitable for both those kernels.  The patch will have to
+be modified for 3.4 as it only has one bug.
+
+Reported-by: Ivan Vasilyev <ivan.vasilyev@gmail.com>
+Tested-by: Ivan Vasilyev <ivan.vasilyev@gmail.com>
+Signed-off-by: NeilBrown <neilb@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+
+---
+ drivers/md/raid10.c |   16 ++++++++++------
+ drivers/md/raid10.h |    2 +-
+ 2 files changed, 11 insertions(+), 7 deletions(-)
+
+--- a/drivers/md/raid10.c
++++ b/drivers/md/raid10.c
+@@ -612,20 +612,24 @@ static int raid10_mergeable_bvec(struct
+               max = biovec->bv_len;
+       if (mddev->merge_check_needed) {
+-              struct r10bio r10_bio;
++              struct {
++                      struct r10bio r10_bio;
++                      struct r10dev devs[conf->copies];
++              } on_stack;
++              struct r10bio *r10_bio = &on_stack.r10_bio;
+               int s;
+-              r10_bio.sector = sector;
+-              raid10_find_phys(conf, &r10_bio);
++              r10_bio->sector = sector;
++              raid10_find_phys(conf, r10_bio);
+               rcu_read_lock();
+               for (s = 0; s < conf->copies; s++) {
+-                      int disk = r10_bio.devs[s].devnum;
++                      int disk = r10_bio->devs[s].devnum;
+                       struct md_rdev *rdev = rcu_dereference(
+                               conf->mirrors[disk].rdev);
+                       if (rdev && !test_bit(Faulty, &rdev->flags)) {
+                               struct request_queue *q =
+                                       bdev_get_queue(rdev->bdev);
+                               if (q->merge_bvec_fn) {
+-                                      bvm->bi_sector = r10_bio.devs[s].addr
++                                      bvm->bi_sector = r10_bio->devs[s].addr
+                                               + rdev->data_offset;
+                                       bvm->bi_bdev = rdev->bdev;
+                                       max = min(max, q->merge_bvec_fn(
+@@ -637,7 +641,7 @@ static int raid10_mergeable_bvec(struct
+                               struct request_queue *q =
+                                       bdev_get_queue(rdev->bdev);
+                               if (q->merge_bvec_fn) {
+-                                      bvm->bi_sector = r10_bio.devs[s].addr
++                                      bvm->bi_sector = r10_bio->devs[s].addr
+                                               + rdev->data_offset;
+                                       bvm->bi_bdev = rdev->bdev;
+                                       max = min(max, q->merge_bvec_fn(
+--- a/drivers/md/raid10.h
++++ b/drivers/md/raid10.h
+@@ -104,7 +104,7 @@ struct r10bio {
+        * We choose the number when they are allocated.
+        * We sometimes need an extra bio to write to the replacement.
+        */
+-      struct {
++      struct r10dev {
+               struct bio      *bio;
+               union {
+                       struct bio      *repl_bio; /* used for resync and
index 76e369ca02de488797bc771fe5afc84fa85e3244..5b8d8c3733de49182c1e0c6464c35df5b8b50f68 100644 (file)
@@ -161,3 +161,6 @@ drm-radeon-force-dma32-to-fix-regression-rs4xx-rs6xx-rs740.patch
 drm-radeon-fix-dig-encoder-selection-on-dce61.patch
 drm-nouveau-fix-booting-with-plymouth-dumb-support.patch
 drm-i915-hdmi-clear-audio-enable-bit-for-hot-plug.patch
+md-raid10-fix-problem-with-on-stack-allocation-of-r10bio-structure.patch
+workqueue-unbound-rebind-morphing-in-rebind_workers-should-be-atomic.patch
+x86-fix-boot-on-twinhead-h12y.patch
diff --git a/queue-3.4/workqueue-unbound-rebind-morphing-in-rebind_workers-should-be-atomic.patch b/queue-3.4/workqueue-unbound-rebind-morphing-in-rebind_workers-should-be-atomic.patch
new file mode 100644 (file)
index 0000000..85ef753
--- /dev/null
@@ -0,0 +1,59 @@
+From 96e65306b81351b656835c15931d1d237b252f27 Mon Sep 17 00:00:00 2001
+From: Lai Jiangshan <laijs@cn.fujitsu.com>
+Date: Sun, 2 Sep 2012 00:28:19 +0800
+Subject: workqueue: UNBOUND -> REBIND morphing in rebind_workers() should be atomic
+
+From: Lai Jiangshan <laijs@cn.fujitsu.com>
+
+commit 96e65306b81351b656835c15931d1d237b252f27 upstream.
+
+The compiler may compile the following code into TWO write/modify
+instructions.
+
+       worker->flags &= ~WORKER_UNBOUND;
+       worker->flags |= WORKER_REBIND;
+
+so the other CPU may temporarily see worker->flags which doesn't have
+either WORKER_UNBOUND or WORKER_REBIND set and perform local wakeup
+prematurely.
+
+Fix it by using single explicit assignment via ACCESS_ONCE().
+
+Because idle workers have another WORKER_NOT_RUNNING flag, this bug
+doesn't exist for them; however, update it to use the same pattern for
+consistency.
+
+tj: Applied the change to idle workers too and updated comments and
+    patch description a bit.
+
+Signed-off-by: Lai Jiangshan <laijs@cn.fujitsu.com>
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ kernel/workqueue.c |    9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+--- a/kernel/workqueue.c
++++ b/kernel/workqueue.c
+@@ -3433,14 +3433,17 @@ static int __cpuinit trustee_thread(void
+       for_each_busy_worker(worker, i, pos, gcwq) {
+               struct work_struct *rebind_work = &worker->rebind_work;
++              unsigned long worker_flags = worker->flags;
+               /*
+                * Rebind_work may race with future cpu hotplug
+                * operations.  Use a separate flag to mark that
+-               * rebinding is scheduled.
++               * rebinding is scheduled.  The morphing should
++               * be atomic.
+                */
+-              worker->flags |= WORKER_REBIND;
+-              worker->flags &= ~WORKER_ROGUE;
++              worker_flags |= WORKER_REBIND;
++              worker_flags &= ~WORKER_ROGUE;
++              ACCESS_ONCE(worker->flags) = worker_flags;
+               /* queue rebind_work, wq doesn't matter, use the default one */
+               if (test_and_set_bit(WORK_STRUCT_PENDING_BIT,
diff --git a/queue-3.4/x86-fix-boot-on-twinhead-h12y.patch b/queue-3.4/x86-fix-boot-on-twinhead-h12y.patch
new file mode 100644 (file)
index 0000000..9262e04
--- /dev/null
@@ -0,0 +1,52 @@
+From 80b3e557371205566a71e569fbfcce5b11f92dbe Mon Sep 17 00:00:00 2001
+From: Alan Cox <alan@linux.intel.com>
+Date: Tue, 15 May 2012 18:44:15 +0100
+Subject: x86: Fix boot on Twinhead H12Y
+
+From: Alan Cox <alan@linux.intel.com>
+
+commit 80b3e557371205566a71e569fbfcce5b11f92dbe upstream.
+
+Despite lots of investigation into why this is needed we don't
+know or have an elegant cure. The only answer found on this
+laptop is to mark a problem region as used so that Linux doesn't
+put anything there.
+
+Currently all the users add reserve= command lines and anyone
+not knowing this needs to find the magic page that documents it.
+Automate it instead.
+
+Signed-off-by: Alan Cox <alan@linux.intel.com>
+Tested-and-bugfixed-by: Arne Fitzenreiter <arne@fitzenreiter.de>
+Resolves-bug: https://bugzilla.kernel.org/show_bug.cgi?id=10231
+Link: http://lkml.kernel.org/r/20120515174347.5109.94551.stgit@bluebook
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/x86/pci/fixup.c |   17 +++++++++++++++++
+ 1 file changed, 17 insertions(+)
+
+--- a/arch/x86/pci/fixup.c
++++ b/arch/x86/pci/fixup.c
+@@ -519,3 +519,20 @@ static void sb600_disable_hpet_bar(struc
+       }
+ }
+ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATI, 0x4385, sb600_disable_hpet_bar);
++
++/*
++ * Twinhead H12Y needs us to block out a region otherwise we map devices
++ * there and any access kills the box.
++ *
++ *   See: https://bugzilla.kernel.org/show_bug.cgi?id=10231
++ *
++ * Match off the LPC and svid/sdid (older kernels lose the bridge subvendor)
++ */
++static void __devinit twinhead_reserve_killing_zone(struct pci_dev *dev)
++{
++        if (dev->subsystem_vendor == 0x14FF && dev->subsystem_device == 0xA003) {
++                pr_info("Reserving memory on Twinhead H12Y\n");
++                request_mem_region(0xFFB00000, 0x100000, "twinhead");
++        }
++}
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x27B9, twinhead_reserve_killing_zone);