]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/md/raid5.c
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
[linux-2.6-omap-h63xx.git] / drivers / md / raid5.c
index 8ee181a01f5206730bd0ad23744247bf51fb289a..a5aad8cad84332a138e741d56ed49bbcf58e1c6c 100644 (file)
@@ -376,7 +376,12 @@ static unsigned long get_stripe_work(struct stripe_head *sh)
                ack++;
 
        sh->ops.count -= ack;
-       BUG_ON(sh->ops.count < 0);
+       if (unlikely(sh->ops.count < 0)) {
+               printk(KERN_ERR "pending: %#lx ops.pending: %#lx ops.ack: %#lx "
+                       "ops.complete: %#lx\n", pending, sh->ops.pending,
+                       sh->ops.ack, sh->ops.complete);
+               BUG();
+       }
 
        return pending;
 }
@@ -550,8 +555,7 @@ static void ops_complete_biofill(void *stripe_head_ref)
                        }
                }
        }
-       clear_bit(STRIPE_OP_BIOFILL, &sh->ops.ack);
-       clear_bit(STRIPE_OP_BIOFILL, &sh->ops.pending);
+       set_bit(STRIPE_OP_BIOFILL, &sh->ops.complete);
 
        return_io(return_bi);
 
@@ -684,7 +688,8 @@ ops_run_prexor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx)
 }
 
 static struct dma_async_tx_descriptor *
-ops_run_biodrain(struct stripe_head *sh, struct dma_async_tx_descriptor *tx)
+ops_run_biodrain(struct stripe_head *sh, struct dma_async_tx_descriptor *tx,
+                unsigned long pending)
 {
        int disks = sh->disks;
        int pd_idx = sh->pd_idx, i;
@@ -692,7 +697,7 @@ ops_run_biodrain(struct stripe_head *sh, struct dma_async_tx_descriptor *tx)
        /* check if prexor is active which means only process blocks
         * that are part of a read-modify-write (Wantprexor)
         */
-       int prexor = test_bit(STRIPE_OP_PREXOR, &sh->ops.pending);
+       int prexor = test_bit(STRIPE_OP_PREXOR, &pending);
 
        pr_debug("%s: stripe %llu\n", __FUNCTION__,
                (unsigned long long)sh->sector);
@@ -769,7 +774,8 @@ static void ops_complete_write(void *stripe_head_ref)
 }
 
 static void
-ops_run_postxor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx)
+ops_run_postxor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx,
+               unsigned long pending)
 {
        /* kernel stack size limits the total number of disks */
        int disks = sh->disks;
@@ -777,7 +783,7 @@ ops_run_postxor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx)
 
        int count = 0, pd_idx = sh->pd_idx, i;
        struct page *xor_dest;
-       int prexor = test_bit(STRIPE_OP_PREXOR, &sh->ops.pending);
+       int prexor = test_bit(STRIPE_OP_PREXOR, &pending);
        unsigned long flags;
        dma_async_tx_callback callback;
 
@@ -804,7 +810,7 @@ ops_run_postxor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx)
        }
 
        /* check whether this postxor is part of a write */
-       callback = test_bit(STRIPE_OP_BIODRAIN, &sh->ops.pending) ?
+       callback = test_bit(STRIPE_OP_BIODRAIN, &pending) ?
                ops_complete_write : ops_complete_postxor;
 
        /* 1/ if we prexor'd then the dest is reused as a source
@@ -892,12 +898,12 @@ static void raid5_run_ops(struct stripe_head *sh, unsigned long pending)
                tx = ops_run_prexor(sh, tx);
 
        if (test_bit(STRIPE_OP_BIODRAIN, &pending)) {
-               tx = ops_run_biodrain(sh, tx);
+               tx = ops_run_biodrain(sh, tx, pending);
                overlap_clear++;
        }
 
        if (test_bit(STRIPE_OP_POSTXOR, &pending))
-               ops_run_postxor(sh, tx);
+               ops_run_postxor(sh, tx, pending);
 
        if (test_bit(STRIPE_OP_CHECK, &pending))
                ops_run_check(sh);
@@ -2620,6 +2626,13 @@ static void handle_stripe5(struct stripe_head *sh)
        s.expanded = test_bit(STRIPE_EXPAND_READY, &sh->state);
        /* Now to look around and see what can be done */
 
+       /* clean-up completed biofill operations */
+       if (test_bit(STRIPE_OP_BIOFILL, &sh->ops.complete)) {
+               clear_bit(STRIPE_OP_BIOFILL, &sh->ops.pending);
+               clear_bit(STRIPE_OP_BIOFILL, &sh->ops.ack);
+               clear_bit(STRIPE_OP_BIOFILL, &sh->ops.complete);
+       }
+
        rcu_read_lock();
        for (i=disks; i--; ) {
                mdk_rdev_t *rdev;
@@ -3175,8 +3188,7 @@ static void unplug_slaves(mddev_t *mddev)
                        atomic_inc(&rdev->nr_pending);
                        rcu_read_unlock();
 
-                       if (r_queue->unplug_fn)
-                               r_queue->unplug_fn(r_queue);
+                       blk_unplug(r_queue);
 
                        rdev_dec_pending(rdev, mddev);
                        rcu_read_lock();