+++ /dev/null
-diff -pur linux-2.6.9-67.orig/drivers/md/raid5.c linux-2.6.9-67/drivers/md/raid5.c
---- linux-2.6.9-67.orig/drivers/md/raid5.c 2009-02-20 16:06:12.000000000 +0800
-+++ linux-2.6.9-67/drivers/md/raid5.c 2009-02-20 16:06:37.000000000 +0800
-@@ -852,6 +852,26 @@ static void add_stripe_bio (struct strip
- }
- }
-
-+/*
-+ * The whole idea is to collect all bio's and then issue them
-+ * disk by disk to assist merging a bit -bzzz
-+ */
-+static void raid5_flush_bios(raid5_conf_t *conf, struct bio *bios[], int raid_disks)
-+{
-+ struct bio *bio, *nbio;
-+ int i;
-+
-+ for (i = 0; i < raid_disks; i++) {
-+ bio = bios[i];
-+ while (bio) {
-+ nbio = bio->bi_next;
-+ bio->bi_next = NULL;
-+ generic_make_request(bio);
-+ bio = nbio;
-+ }
-+ bios[i] = NULL;
-+ }
-+}
-
- /*
- * handle_stripe - do things to a stripe.
-@@ -871,7 +891,7 @@ static void add_stripe_bio (struct strip
- *
- */
-
--static void handle_stripe(struct stripe_head *sh)
-+static void handle_stripe(struct stripe_head *sh, struct bio *bios[])
- {
- raid5_conf_t *conf = sh->raid_conf;
- int disks = conf->raid_disks;
-@@ -1291,7 +1311,11 @@ static void handle_stripe(struct stripe_
- bi->bi_size = STRIPE_SIZE;
- bi->bi_next = NULL;
- atomic_inc(&conf->out_reqs_in_queue);
-- generic_make_request(bi);
-+ if (bios) {
-+ bi->bi_next = bios[i];
-+ bios[i] = bi;
-+ } else
-+ generic_make_request(bi);
- } else {
- PRINTK("skip op %ld on disc %d for sector %llu\n",
- bi->bi_rw, i, (unsigned long long)sh->sector);
-@@ -1416,6 +1440,7 @@ static int make_request (request_queue_t
- int sectors_per_chunk = conf->chunk_size >> 9;
- int stripes_per_chunk, sectors_per_block;
- int sectors_per_stripe;
-+ struct bio *bios[MD_SB_DISKS];
- int i, j;
-
- if (unlikely(bio_barrier(bi))) {
-@@ -1450,6 +1475,7 @@ static int make_request (request_queue_t
- sector_div(block, sectors_per_block);
- sectors = bi->bi_size >> 9;
-
-+ memset(&bios, 0, sizeof(bios));
- repeat:
- stripe = block * (sectors_per_block / data_disks);
- b_sector = stripe * data_disks;
-@@ -1469,9 +1495,17 @@ repeat:
- new_sector = raid5_compute_sector(r_sector, raid_disks,
- data_disks, &dd_idx,
- &pd_idx, conf);
-- if (sh == NULL)
-- sh = get_active_stripe(conf, new_sector, pd_idx,
-- (bi->bi_rw&RWA_MASK));
-+ if (sh == NULL) {
-+ /* first, try to get stripe w/o blocking
-+ * if we can't, then it's time to submit
-+ * all collected bio's in order to free
-+ * some space in the cache -bzzz */
-+ sh = get_active_stripe(conf, new_sector, pd_idx, 1);
-+ if (!sh && !(bi->bi_rw&RWA_MASK)) {
-+ raid5_flush_bios(conf, bios, raid_disks);
-+ sh = get_active_stripe(conf, new_sector, pd_idx, 0);
-+ }
-+ }
- if (sh) {
- add_stripe_bio(sh, bi, dd_idx, (bi->bi_rw&RW_MASK));
- } else {
-@@ -1491,7 +1525,7 @@ repeat:
- }
- if (sh) {
- raid5_plug_device(conf);
-- handle_stripe(sh);
-+ handle_stripe(sh, bios);
- release_stripe(sh);
- sh = NULL;
- }
-@@ -1501,6 +1535,9 @@ repeat:
- if (sectors > 0)
- goto repeat;
-
-+ /* now flush all bio's */
-+ raid5_flush_bios(conf, bios, raid_disks);
-+
- spin_lock_irq(&conf->device_lock);
- if (--bi->bi_phys_segments == 0) {
- int bytes = bi->bi_size;
-@@ -1556,7 +1593,7 @@ static int sync_request (mddev_t *mddev,
- clear_bit(STRIPE_INSYNC, &sh->state);
- spin_unlock(&sh->lock);
-
-- handle_stripe(sh);
-+ handle_stripe(sh, NULL);
- release_stripe(sh);
-
- return STRIPE_SECTORS;
-@@ -1605,9 +1642,11 @@ static void raid5d (mddev_t *mddev)
-
- handled++;
- atomic_inc(&conf->handled_in_raid5d);
-- handle_stripe(sh);
-+ handle_stripe(sh, NULL);
- release_stripe(sh);
-
-+ cond_resched();
-+
- spin_lock_irq(&conf->device_lock);
- }
- PRINTK("%d stripes handled\n", handled);