Revert "block: don't call into the driver for BLKROSET"
[platform/kernel/linux-rpi.git] / drivers / md / raid5.c
index 19e497a..d5b330c 100644 (file)
@@ -36,6 +36,7 @@
  */
 
 #include <linux/blkdev.h>
+#include <linux/delay.h>
 #include <linux/kthread.h>
 #include <linux/raid/pq.h>
 #include <linux/async_tx.h>
@@ -2217,8 +2218,9 @@ static void raid_run_ops(struct stripe_head *sh, unsigned long ops_request)
        struct raid5_percpu *percpu;
        unsigned long cpu;
 
-       cpu = get_cpu();
+       cpu = get_cpu_light();
        percpu = per_cpu_ptr(conf->percpu, cpu);
+       spin_lock(&percpu->lock);
        if (test_bit(STRIPE_OP_BIOFILL, &ops_request)) {
                ops_run_biofill(sh);
                overlap_clear++;
@@ -2277,7 +2279,8 @@ static void raid_run_ops(struct stripe_head *sh, unsigned long ops_request)
                        if (test_and_clear_bit(R5_Overlap, &dev->flags))
                                wake_up(&sh->raid_conf->wait_for_overlap);
                }
-       put_cpu();
+       spin_unlock(&percpu->lock);
+       put_cpu_light();
 }
 
 static void free_stripe(struct kmem_cache *sc, struct stripe_head *sh)
@@ -3936,7 +3939,7 @@ static void handle_stripe_fill(struct stripe_head *sh,
                 * back cache (prexor with orig_page, and then xor with
                 * page) in the read path
                 */
-               if (s->injournal && s->failed) {
+               if (s->to_read && s->injournal && s->failed) {
                        if (test_bit(STRIPE_R5C_CACHING, &sh->state))
                                r5c_make_stripe_write_out(sh);
                        goto out;
@@ -5430,7 +5433,6 @@ static int raid5_read_one_chunk(struct mddev *mddev, struct bio *raid_bio)
 
        if (is_badblock(rdev, sector, bio_sectors(raid_bio), &first_bad,
                        &bad_sectors)) {
-               bio_put(raid_bio);
                rdev_dec_pending(rdev, mddev);
                return 0;
        }
@@ -6522,7 +6524,18 @@ static void raid5d(struct md_thread *thread)
                        spin_unlock_irq(&conf->device_lock);
                        md_check_recovery(mddev);
                        spin_lock_irq(&conf->device_lock);
+
+                       /*
+                        * Waiting on MD_SB_CHANGE_PENDING below may deadlock
+                        * seeing md_check_recovery() is needed to clear
+                        * the flag when using mdmon.
+                        */
+                       continue;
                }
+
+               wait_event_lock_irq(mddev->sb_wait,
+                       !test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags),
+                       conf->device_lock);
        }
        pr_debug("%d stripes handled\n", handled);
 
@@ -7099,6 +7112,7 @@ static int raid456_cpu_up_prepare(unsigned int cpu, struct hlist_node *node)
                        __func__, cpu);
                return -ENOMEM;
        }
+       spin_lock_init(&per_cpu_ptr(conf->percpu, cpu)->lock);
        return 0;
 }