Whamcloud - gitweb
land b1_5 onto HEAD
[fs/lustre-release.git] / lustre / kernel_patches / patches / raid5-merge-ios.patch
diff --git a/lustre/kernel_patches/patches/raid5-merge-ios.patch b/lustre/kernel_patches/patches/raid5-merge-ios.patch
new file mode 100644 (file)
index 0000000..3f5cbbc
--- /dev/null
@@ -0,0 +1,129 @@
+Merge IO requests to try and get larger requests on underlying drives.
+
+Index: linux-2.6.9/drivers/md/raid5.c
+===================================================================
+--- linux-2.6.9.orig/drivers/md/raid5.c        2006-05-22 00:10:04.000000000 +0400
++++ linux-2.6.9/drivers/md/raid5.c     2006-05-22 00:10:06.000000000 +0400
+@@ -934,6 +934,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.
+@@ -953,7 +973,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;
+@@ -1376,7 +1396,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);
+@@ -1501,6 +1525,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;
+       atomic_inc(&conf->in_reqs_in_queue);
+@@ -1530,6 +1555,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;
+@@ -1549,9 +1575,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 {
+@@ -1571,7 +1605,7 @@ repeat:
+               }
+               if (sh) {
+                       raid5_plug_device(conf);
+-                      handle_stripe(sh);
++                      handle_stripe(sh, bios);
+                       release_stripe(sh);
+                       sh = NULL;
+               }
+@@ -1581,6 +1615,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;
+@@ -1636,7 +1673,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;
+@@ -1685,7 +1722,7 @@ static void raid5d (mddev_t *mddev)
+               
+               handled++;
+               atomic_inc(&conf->handled_in_raid5d);
+-              handle_stripe(sh);
++              handle_stripe(sh, NULL);
+               release_stripe(sh);
+               spin_lock_irq(&conf->device_lock);