Whamcloud - gitweb
Branch HEAD
[fs/lustre-release.git] / lustre / kernel_patches / patches / raid5-merge-ios.patch
1 diff -pur linux-2.6.9-67.orig/drivers/md/raid5.c linux-2.6.9-67/drivers/md/raid5.c
2 --- linux-2.6.9-67.orig/drivers/md/raid5.c      2009-02-20 16:06:12.000000000 +0800
3 +++ linux-2.6.9-67/drivers/md/raid5.c   2009-02-20 16:06:37.000000000 +0800
4 @@ -852,6 +852,26 @@ static void add_stripe_bio (struct strip
5         }
6  }
7  
8 +/*
9 + * The whole idea is to collect all bio's and then issue them
10 + * disk by disk to assist merging a bit -bzzz
11 + */
12 +static void raid5_flush_bios(raid5_conf_t *conf, struct bio *bios[], int raid_disks)
13 +{
14 +       struct bio *bio, *nbio;
15 +       int i;
16 +
17 +       for (i = 0; i < raid_disks; i++) {
18 +               bio = bios[i];
19 +               while (bio) {
20 +                       nbio = bio->bi_next;
21 +                       bio->bi_next = NULL;
22 +                       generic_make_request(bio);
23 +                       bio = nbio;
24 +               }
25 +               bios[i] = NULL;
26 +       }
27 +}
28  
29  /*
30   * handle_stripe - do things to a stripe.
31 @@ -871,7 +891,7 @@ static void add_stripe_bio (struct strip
32   *
33   */
34   
35 -static void handle_stripe(struct stripe_head *sh)
36 +static void handle_stripe(struct stripe_head *sh, struct bio *bios[])
37  {
38         raid5_conf_t *conf = sh->raid_conf;
39         int disks = conf->raid_disks;
40 @@ -1291,7 +1311,11 @@ static void handle_stripe(struct stripe_
41                         bi->bi_size = STRIPE_SIZE;
42                         bi->bi_next = NULL;
43                         atomic_inc(&conf->out_reqs_in_queue);
44 -                       generic_make_request(bi);
45 +                       if (bios) {
46 +                               bi->bi_next = bios[i];
47 +                               bios[i] = bi;
48 +                       } else
49 +                               generic_make_request(bi);
50                 } else {
51                         PRINTK("skip op %ld on disc %d for sector %llu\n",
52                                 bi->bi_rw, i, (unsigned long long)sh->sector);
53 @@ -1416,6 +1440,7 @@ static int make_request (request_queue_t
54         int sectors_per_chunk = conf->chunk_size >> 9;
55         int stripes_per_chunk, sectors_per_block;
56         int sectors_per_stripe;
57 +       struct bio *bios[MD_SB_DISKS];
58         int i, j;
59  
60         if (unlikely(bio_barrier(bi))) {
61 @@ -1450,6 +1475,7 @@ static int make_request (request_queue_t
62         sector_div(block, sectors_per_block);
63         sectors = bi->bi_size >> 9;
64  
65 +       memset(&bios, 0, sizeof(bios));
66  repeat:
67         stripe = block * (sectors_per_block / data_disks);
68         b_sector = stripe * data_disks;
69 @@ -1469,9 +1495,17 @@ repeat:
70                         new_sector = raid5_compute_sector(r_sector, raid_disks,
71                                                         data_disks, &dd_idx, 
72                                                         &pd_idx, conf);
73 -                       if (sh == NULL)
74 -                               sh = get_active_stripe(conf, new_sector, pd_idx,
75 -                                                       (bi->bi_rw&RWA_MASK));
76 +                       if (sh == NULL) {
77 +                               /* first, try to get stripe w/o blocking
78 +                                * if we can't, then it's time to submit
79 +                                * all collected bio's in order to free
80 +                                * some space in the cache -bzzz */
81 +                               sh = get_active_stripe(conf, new_sector, pd_idx, 1);
82 +                               if (!sh && !(bi->bi_rw&RWA_MASK)) {
83 +                                       raid5_flush_bios(conf, bios, raid_disks);
84 +                                       sh = get_active_stripe(conf, new_sector, pd_idx, 0);
85 +                               }
86 +                       }
87                         if (sh) {
88                                 add_stripe_bio(sh, bi, dd_idx, (bi->bi_rw&RW_MASK));
89                         } else {
90 @@ -1491,7 +1525,7 @@ repeat:
91                 }
92                 if (sh) {
93                         raid5_plug_device(conf);
94 -                       handle_stripe(sh);
95 +                       handle_stripe(sh, bios);
96                         release_stripe(sh);
97                         sh = NULL;
98                 }
99 @@ -1501,6 +1535,9 @@ repeat:
100         if (sectors > 0)
101                 goto repeat;
102  
103 +       /* now flush all bio's */
104 +       raid5_flush_bios(conf, bios, raid_disks);
105 +
106         spin_lock_irq(&conf->device_lock);
107         if (--bi->bi_phys_segments == 0) {
108                 int bytes = bi->bi_size;
109 @@ -1556,7 +1593,7 @@ static int sync_request (mddev_t *mddev,
110         clear_bit(STRIPE_INSYNC, &sh->state);
111         spin_unlock(&sh->lock);
112  
113 -       handle_stripe(sh);
114 +       handle_stripe(sh, NULL);
115         release_stripe(sh);
116  
117         return STRIPE_SECTORS;
118 @@ -1605,9 +1642,11 @@ static void raid5d (mddev_t *mddev)
119                 
120                 handled++;
121                 atomic_inc(&conf->handled_in_raid5d);
122 -               handle_stripe(sh);
123 +               handle_stripe(sh, NULL);
124                 release_stripe(sh);
125  
126 +               cond_resched();
127 +
128                 spin_lock_irq(&conf->device_lock);
129         }
130         PRINTK("%d stripes handled\n", handled);