]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 16 Aug 2013 04:47:07 +0000 (21:47 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 16 Aug 2013 04:47:07 +0000 (21:47 -0700)
added patches:
md-raid1-raid10-use-freeze_array-in-place-of-raise_barrier.patch

queue-3.4/md-raid1-raid10-use-freeze_array-in-place-of-raise_barrier.patch [new file with mode: 0644]
queue-3.4/series

diff --git a/queue-3.4/md-raid1-raid10-use-freeze_array-in-place-of-raise_barrier.patch b/queue-3.4/md-raid1-raid10-use-freeze_array-in-place-of-raise_barrier.patch
new file mode 100644 (file)
index 0000000..5383a60
--- /dev/null
@@ -0,0 +1,180 @@
+From e2d59925221cd562e07fee38ec8839f7209ae603 Mon Sep 17 00:00:00 2001
+From: NeilBrown <neilb@suse.de>
+Date: Wed, 12 Jun 2013 11:01:22 +1000
+Subject: md/raid1,raid10: use freeze_array in place of raise_barrier
+ in various places.
+
+From: NeilBrown <neilb@suse.de>
+
+commit e2d59925221cd562e07fee38ec8839f7209ae603 upstream.
+
+Various places in raid1 and raid10 are calling raise_barrier when they
+really should call freeze_array.
+The former is only intended to be called from "make_request".
+The later has extra checks for 'nr_queued' and makes a call to
+flush_pending_writes(), so it is safe to call it from within the
+management thread.
+
+Using raise_barrier will sometimes deadlock.  Using freeze_array
+should not.
+
+As 'freeze_array' currently expects one request to be pending (in
+handle_read_error - the only previous caller), we need to pass
+it the number of pending requests (extra) to ignore.
+
+The deadlock was made particularly noticeable by commits
+050b66152f87c7 (raid10) and 6b740b8d79252f13 (raid1) which
+appeared in 3.4, so the fix is appropriate for any -stable
+kernel since then.
+
+This patch probably won't apply directly to some early kernels and
+will need to be applied by hand.
+
+Cc: stable@vger.kernel.org
+Reported-by: Alexander Lyakas <alex.bolshoy@gmail.com>
+Signed-off-by: NeilBrown <neilb@suse.de>
+[adjust context to make it can be apply on top of 3.4 ]
+Signed-off-by: Jack Wang <jinpu.wang@profitbricks.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/md/raid1.c  |   22 +++++++++++-----------
+ drivers/md/raid10.c |   14 +++++++-------
+ 2 files changed, 18 insertions(+), 18 deletions(-)
+
+--- a/drivers/md/raid1.c
++++ b/drivers/md/raid1.c
+@@ -812,17 +812,17 @@ static void allow_barrier(struct r1conf
+       wake_up(&conf->wait_barrier);
+ }
+-static void freeze_array(struct r1conf *conf)
++static void freeze_array(struct r1conf *conf, int extra)
+ {
+       /* stop syncio and normal IO and wait for everything to
+        * go quite.
+        * We increment barrier and nr_waiting, and then
+-       * wait until nr_pending match nr_queued+1
++       * wait until nr_pending match nr_queued+extra
+        * This is called in the context of one normal IO request
+        * that has failed. Thus any sync request that might be pending
+        * will be blocked by nr_pending, and we need to wait for
+        * pending IO requests to complete or be queued for re-try.
+-       * Thus the number queued (nr_queued) plus this request (1)
++       * Thus the number queued (nr_queued) plus this request (extra)
+        * must match the number of pending IOs (nr_pending) before
+        * we continue.
+        */
+@@ -830,7 +830,7 @@ static void freeze_array(struct r1conf *
+       conf->barrier++;
+       conf->nr_waiting++;
+       wait_event_lock_irq(conf->wait_barrier,
+-                          conf->nr_pending == conf->nr_queued+1,
++                          conf->nr_pending == conf->nr_queued+extra,
+                           conf->resync_lock,
+                           flush_pending_writes(conf));
+       spin_unlock_irq(&conf->resync_lock);
+@@ -1432,8 +1432,8 @@ static int raid1_add_disk(struct mddev *
+                * we wait for all outstanding requests to complete.
+                */
+               synchronize_sched();
+-              raise_barrier(conf);
+-              lower_barrier(conf);
++              freeze_array(conf, 0);
++              unfreeze_array(conf);
+               clear_bit(Unmerged, &rdev->flags);
+       }
+       md_integrity_add_rdev(rdev, mddev);
+@@ -1481,11 +1481,11 @@ static int raid1_remove_disk(struct mdde
+                        */
+                       struct md_rdev *repl =
+                               conf->mirrors[conf->raid_disks + number].rdev;
+-                      raise_barrier(conf);
++                      freeze_array(conf, 0);
+                       clear_bit(Replacement, &repl->flags);
+                       p->rdev = repl;
+                       conf->mirrors[conf->raid_disks + number].rdev = NULL;
+-                      lower_barrier(conf);
++                      unfreeze_array(conf);
+                       clear_bit(WantReplacement, &rdev->flags);
+               } else
+                       clear_bit(WantReplacement, &rdev->flags);
+@@ -2100,7 +2100,7 @@ static void handle_read_error(struct r1c
+        * frozen
+        */
+       if (mddev->ro == 0) {
+-              freeze_array(conf);
++              freeze_array(conf, 1);
+               fix_read_error(conf, r1_bio->read_disk,
+                              r1_bio->sector, r1_bio->sectors);
+               unfreeze_array(conf);
+@@ -2855,7 +2855,7 @@ static int raid1_reshape(struct mddev *m
+               return -ENOMEM;
+       }
+-      raise_barrier(conf);
++      freeze_array(conf, 0);
+       /* ok, everything is stopped */
+       oldpool = conf->r1bio_pool;
+@@ -2887,7 +2887,7 @@ static int raid1_reshape(struct mddev *m
+       mddev->delta_disks = 0;
+       conf->last_used = 0; /* just make sure it is in-range */
+-      lower_barrier(conf);
++      unfreeze_array(conf);
+       set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
+       md_wakeup_thread(mddev->thread);
+--- a/drivers/md/raid10.c
++++ b/drivers/md/raid10.c
+@@ -952,17 +952,17 @@ static void allow_barrier(struct r10conf
+       wake_up(&conf->wait_barrier);
+ }
+-static void freeze_array(struct r10conf *conf)
++static void freeze_array(struct r10conf *conf, int extra)
+ {
+       /* stop syncio and normal IO and wait for everything to
+        * go quiet.
+        * We increment barrier and nr_waiting, and then
+-       * wait until nr_pending match nr_queued+1
++       * wait until nr_pending match nr_queued+extra
+        * This is called in the context of one normal IO request
+        * that has failed. Thus any sync request that might be pending
+        * will be blocked by nr_pending, and we need to wait for
+        * pending IO requests to complete or be queued for re-try.
+-       * Thus the number queued (nr_queued) plus this request (1)
++       * Thus the number queued (nr_queued) plus this request (extra)
+        * must match the number of pending IOs (nr_pending) before
+        * we continue.
+        */
+@@ -970,7 +970,7 @@ static void freeze_array(struct r10conf
+       conf->barrier++;
+       conf->nr_waiting++;
+       wait_event_lock_irq(conf->wait_barrier,
+-                          conf->nr_pending == conf->nr_queued+1,
++                          conf->nr_pending == conf->nr_queued+extra,
+                           conf->resync_lock,
+                           flush_pending_writes(conf));
+@@ -1619,8 +1619,8 @@ static int raid10_add_disk(struct mddev
+                * we wait for all outstanding requests to complete.
+                */
+               synchronize_sched();
+-              raise_barrier(conf, 0);
+-              lower_barrier(conf);
++              freeze_array(conf, 0);
++              unfreeze_array(conf);
+               clear_bit(Unmerged, &rdev->flags);
+       }
+       md_integrity_add_rdev(rdev, mddev);
+@@ -2410,7 +2410,7 @@ static void handle_read_error(struct mdd
+       r10_bio->devs[slot].bio = NULL;
+       if (mddev->ro == 0) {
+-              freeze_array(conf);
++              freeze_array(conf, 1);
+               fix_read_error(conf, mddev, r10_bio);
+               unfreeze_array(conf);
+       } else
index e857d57567380312cced1a3908e1e249b8e85d6d..11025beb3cd7536ccb40fe4791e0d105798462d7 100644 (file)
@@ -15,3 +15,4 @@ frv-use-correct-size-for-task_struct-allocation.patch
 frv-use-core-allocator-for-task_struct.patch
 powerpc-numa-avoid-stupid-uninitialized-warning-from-gcc.patch
 alpha-makefile-don-t-enforce-small-data-model-for-kernel-builds.patch
+md-raid1-raid10-use-freeze_array-in-place-of-raise_barrier.patch