From: Greg Kroah-Hartman Date: Thu, 27 Sep 2012 00:13:53 +0000 (-0700) Subject: 3.4-stable patches X-Git-Tag: v3.0.44~48 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=28040f08230b7a1d50c51ff103e3a2f0e73fedc0;p=thirdparty%2Fkernel%2Fstable-queue.git 3.4-stable patches 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 --- 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 index 00000000000..a5e1411e0b2 --- /dev/null +++ b/queue-3.4/md-raid10-fix-problem-with-on-stack-allocation-of-r10bio-structure.patch @@ -0,0 +1,87 @@ +From e0ee778528bbaad28a5c69d2e219269a3a096607 Mon Sep 17 00:00:00 2001 +From: NeilBrown +Date: Sat, 18 Aug 2012 09:51:42 +1000 +Subject: md/raid10: fix problem with on-stack allocation of r10bio structure. + +From: NeilBrown + +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 +Tested-by: Ivan Vasilyev +Signed-off-by: NeilBrown +Signed-off-by: Greg Kroah-Hartman + + +--- + 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 diff --git a/queue-3.4/series b/queue-3.4/series index 76e369ca02d..5b8d8c3733d 100644 --- a/queue-3.4/series +++ b/queue-3.4/series @@ -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 index 00000000000..85ef7530637 --- /dev/null +++ b/queue-3.4/workqueue-unbound-rebind-morphing-in-rebind_workers-should-be-atomic.patch @@ -0,0 +1,59 @@ +From 96e65306b81351b656835c15931d1d237b252f27 Mon Sep 17 00:00:00 2001 +From: Lai Jiangshan +Date: Sun, 2 Sep 2012 00:28:19 +0800 +Subject: workqueue: UNBOUND -> REBIND morphing in rebind_workers() should be atomic + +From: Lai Jiangshan + +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 +Signed-off-by: Tejun Heo +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..9262e048b7c --- /dev/null +++ b/queue-3.4/x86-fix-boot-on-twinhead-h12y.patch @@ -0,0 +1,52 @@ +From 80b3e557371205566a71e569fbfcce5b11f92dbe Mon Sep 17 00:00:00 2001 +From: Alan Cox +Date: Tue, 15 May 2012 18:44:15 +0100 +Subject: x86: Fix boot on Twinhead H12Y + +From: Alan Cox + +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 +Tested-and-bugfixed-by: Arne Fitzenreiter +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 +Signed-off-by: Greg Kroah-Hartman + +--- + 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);