Whamcloud - gitweb
Branch HEAD
[fs/lustre-release.git] / lustre / kernel_patches / patches / raid5-merge-ios-rhel5.patch
1 diff -pur b/drivers/md/raid5.c a/drivers/md/raid5.c
2 --- b/drivers/md/raid5.c        2009-02-20 15:56:36.000000000 +0800
3 +++ a/drivers/md/raid5.c        2009-02-20 15:57:49.000000000 +0800
4 @@ -1277,7 +1277,26 @@ static void compute_block_2(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   * Each stripe/dev can have one or more bion attached.
31 @@ -1392,7 +1411,7 @@ static int stripe_to_pdidx(sector_t stri
32   *
33   */
34   
35 -static void handle_stripe5(struct stripe_head *sh)
36 +static void handle_stripe5(struct stripe_head *sh, struct bio *bios[])
37  {
38         raid5_conf_t *conf = sh->raid_conf;
39         int disks = sh->disks;
40 @@ -1939,7 +1958,11 @@ static void handle_stripe5(struct stripe
41                             test_bit(R5_ReWrite, &sh->dev[i].flags))
42                                 atomic_add(STRIPE_SECTORS, &rdev->corrected_errors);
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                         if (rw == 1)
52                                 set_bit(STRIPE_DEGRADED, &sh->state);
53 @@ -1951,7 +1974,7 @@ static void handle_stripe5(struct stripe
54         }
55  }
56  
57 -static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
58 +static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page, struct bio *bios[])
59  {
60         raid6_conf_t *conf = sh->raid_conf;
61         int disks = conf->raid_disks;
62 @@ -2499,7 +2522,11 @@ static void handle_stripe6(struct stripe
63                         if (rw == WRITE &&
64                             test_bit(R5_ReWrite, &sh->dev[i].flags))
65                                 atomic_add(STRIPE_SECTORS, &rdev->corrected_errors);
66 -                       generic_make_request(bi);
67 +                       if (bios) {
68 +                               bi->bi_next = bios[i];
69 +                               bios[i] = bi;
70 +                       } else
71 +                               generic_make_request(bi);
72                         atomic_inc(&conf->out_reqs_in_queue);
73                 } else {
74                         if (rw == 1)
75 @@ -2512,12 +2539,12 @@ static void handle_stripe6(struct stripe
76         }
77  }
78  
79 -static void handle_stripe(struct stripe_head *sh, struct page *tmp_page)
80 +static void handle_stripe(struct stripe_head *sh, struct page *tmp_page, struct bio *bios[])
81  {
82         if (sh->raid_conf->level == 6)
83 -               handle_stripe6(sh, tmp_page);
84 +               handle_stripe6(sh, tmp_page, bios);
85         else
86 -               handle_stripe5(sh);
87 +               handle_stripe5(sh, bios);
88  }
89  
90  
91 @@ -2670,6 +2697,7 @@ static int make_request(request_queue_t 
92         int stripes_per_chunk, sectors_per_block;
93         int sectors_per_stripe;
94         int i, j;
95 +       struct bio *bios[MD_SB_DISKS];
96  
97         DEFINE_WAIT(w);
98         int disks, data_disks;
99 @@ -2698,6 +2726,7 @@ static int make_request(request_queue_t 
100         sectors = bi->bi_size >> 9;
101         stripes_per_chunk = conf->chunk_size / STRIPE_SIZE;
102  
103 +       memset(&bios, 0, sizeof(bios));
104  redo_bio:
105         /* stripe by stripe handle needs a stable raid layout, so if this
106          * reuqest covers the expanding region, wait it over. 
107 @@ -2756,8 +2785,10 @@ retry:
108                                          * the raid layout has been changed, we have to redo the 
109                                          * whole bio because we don't which sectors in it has been
110                                          * done, and which is not done. -jay */
111 -                                       if (raid5_redo_bio(conf, bi, disks, logical_sector))
112 +                                       if (raid5_redo_bio(conf, bi, disks, logical_sector)) {
113 +                                               raid5_flush_bios(conf, bios, disks);
114                                                 goto redo_bio;
115 +                                       }
116  
117                                         if (test_bit(STRIPE_EXPANDING, &sh->state)) {
118                                                 /* Stripe is busy expanding or
119 @@ -2766,6 +2797,7 @@ retry:
120                                                  */
121                                                 release_stripe(sh);
122                                                 sh = NULL;
123 +                                               raid5_flush_bios(conf, bios, disks);
124                                                 raid5_unplug_device(mddev->queue);
125                                                 schedule();
126                                                 goto retry;
127 @@ -2784,17 +2816,19 @@ retry:
128                          */
129                         if (r_sector >= mddev->suspend_lo &&
130                             r_sector < mddev->suspend_hi) {
131 -                               handle_stripe(sh, NULL);
132 +                               handle_stripe(sh, NULL, NULL);
133                                 release_stripe(sh);
134                                 sh = NULL;
135 +                               raid5_flush_bios(conf, bios, disks);
136                                 schedule();
137                                 goto retry;
138                         }
139  
140                         if (!add_stripe_bio(sh, bi, dd_idx, (bi->bi_rw&RW_MASK))) {
141 -                               handle_stripe(sh, NULL);
142 +                               handle_stripe(sh, NULL, NULL);
143                                 release_stripe(sh);
144                                 sh = NULL;
145 +                               raid5_flush_bios(conf, bios, disks);
146                                 raid5_unplug_device(mddev->queue);
147                                 schedule();
148                                 goto retry;
149 @@ -2810,7 +2844,7 @@ retry:
150                         r_sector += sectors_per_chunk;
151                 }
152                 if (sh) {
153 -                       handle_stripe(sh, NULL);
154 +                       handle_stripe(sh, NULL, bios);
155                         release_stripe(sh);
156                         sh = NULL;
157                 }
158 @@ -2820,6 +2854,9 @@ retry:
159         if (sectors > 0)
160                 goto repeat;
161  
162 +       /* flush all of the bios */
163 +       raid5_flush_bios(conf, bios, disks);
164 +
165         spin_lock_irq(&conf->device_lock);
166         remaining = --bi->bi_phys_segments;
167         spin_unlock_irq(&conf->device_lock);
168 @@ -3035,7 +3072,7 @@ static inline sector_t sync_request(mdde
169         clear_bit(STRIPE_INSYNC, &sh->state);
170         spin_unlock(&sh->lock);
171  
172 -       handle_stripe(sh, NULL);
173 +       handle_stripe(sh, NULL, NULL);
174         release_stripe(sh);
175  
176         return STRIPE_SECTORS;
177 @@ -3091,9 +3128,11 @@ static void raid5d (mddev_t *mddev)
178                 
179                 handled++;
180                 atomic_inc(&conf->handled_in_raid5d);
181 -               handle_stripe(sh, conf->spare_page);
182 +               handle_stripe(sh, conf->spare_page, NULL);
183                 release_stripe(sh);
184  
185 +               cond_resched();
186 +
187                 spin_lock_irq(&conf->device_lock);
188         }
189         PRINTK("%d stripes handled\n", handled);