]> git.ipfire.org Git - ipfire-2.x.git/blob - src/patches/suse-2.6.27.39/patches.fixes/0013-md-raid5-Add-support-for-new-layouts-for-raid5-and-r.patch
Fix oinkmaster patch.
[ipfire-2.x.git] / src / patches / suse-2.6.27.39 / patches.fixes / 0013-md-raid5-Add-support-for-new-layouts-for-raid5-and-r.patch
1 From 99c0fb5f92828ae96909d390f2df137b89093b37 Mon Sep 17 00:00:00 2001
2 From: NeilBrown <neilb@suse.de>
3 Date: Tue, 31 Mar 2009 14:39:38 +1100
4 Subject: [PATCH] md/raid5: Add support for new layouts for raid5 and raid6.
5
6 DDF uses different layouts for P and Q blocks than current md/raid6
7 so add those that are missing.
8 Also add support for RAID6 layouts that are identical to various
9 raid5 layouts with the simple addition of one device to hold all of
10 the 'Q' blocks.
11 Finally add 'raid5' layouts to match raid4.
12 These last to will allow online level conversion.
13
14 Note that this does not provide correct support for DDF/raid6 yet
15 as the order in which data blocks are summed to produce the Q block
16 is significant and different between current md code and DDF
17 requirements.
18
19 Signed-off-by: NeilBrown <neilb@suse.de>
20 ---
21 drivers/md/raid5.c | 151 ++++++++++++++++++++++++++++++++++++++++-----
22 include/linux/raid/raid5.h | 61 ++++++++++++++++--
23 2 files changed, 193 insertions(+), 19 deletions(-)
24
25 --- linux-2.6.27-SLE11_BRANCH.orig/drivers/md/raid5.c
26 +++ linux-2.6.27-SLE11_BRANCH/drivers/md/raid5.c
27 @@ -1100,7 +1100,7 @@ static void shrink_stripes(raid5_conf_t
28
29 static void raid5_end_read_request(struct bio * bi, int error)
30 {
31 - struct stripe_head *sh = bi->bi_private;
32 + struct stripe_head *sh = bi->bi_private;
33 raid5_conf_t *conf = sh->raid_conf;
34 int disks = sh->disks, i;
35 int uptodate = test_bit(BIO_UPTODATE, &bi->bi_flags);
36 @@ -1182,7 +1182,7 @@ static void raid5_end_read_request(struc
37
38 static void raid5_end_write_request (struct bio *bi, int error)
39 {
40 - struct stripe_head *sh = bi->bi_private;
41 + struct stripe_head *sh = bi->bi_private;
42 raid5_conf_t *conf = sh->raid_conf;
43 int disks = sh->disks, i;
44 int uptodate = test_bit(BIO_UPTODATE, &bi->bi_flags);
45 @@ -1322,20 +1322,27 @@ static sector_t raid5_compute_sector(rai
46 pd_idx = stripe % raid_disks;
47 *dd_idx = (pd_idx + 1 + *dd_idx) % raid_disks;
48 break;
49 + case ALGORITHM_PARITY_0:
50 + pd_idx = 0;
51 + (*dd_idx)++;
52 + break;
53 + case ALGORITHM_PARITY_N:
54 + pd_idx = data_disks;
55 + break;
56 default:
57 printk(KERN_ERR "raid5: unsupported algorithm %d\n",
58 conf->algorithm);
59 + BUG();
60 }
61 break;
62 case 6:
63
64 - /**** FIX THIS ****/
65 switch (conf->algorithm) {
66 case ALGORITHM_LEFT_ASYMMETRIC:
67 pd_idx = raid_disks - 1 - (stripe % raid_disks);
68 qd_idx = pd_idx + 1;
69 if (pd_idx == raid_disks-1) {
70 - (*dd_idx)++; /* Q D D D P */
71 + (*dd_idx)++; /* Q D D D P */
72 qd_idx = 0;
73 } else if (*dd_idx >= pd_idx)
74 (*dd_idx) += 2; /* D D P Q D */
75 @@ -1344,7 +1351,7 @@ static sector_t raid5_compute_sector(rai
76 pd_idx = stripe % raid_disks;
77 qd_idx = pd_idx + 1;
78 if (pd_idx == raid_disks-1) {
79 - (*dd_idx)++; /* Q D D D P */
80 + (*dd_idx)++; /* Q D D D P */
81 qd_idx = 0;
82 } else if (*dd_idx >= pd_idx)
83 (*dd_idx) += 2; /* D D P Q D */
84 @@ -1359,9 +1366,89 @@ static sector_t raid5_compute_sector(rai
85 qd_idx = (pd_idx + 1) % raid_disks;
86 *dd_idx = (pd_idx + 2 + *dd_idx) % raid_disks;
87 break;
88 +
89 + case ALGORITHM_PARITY_0:
90 + pd_idx = 0;
91 + qd_idx = 1;
92 + (*dd_idx) += 2;
93 + break;
94 + case ALGORITHM_PARITY_N:
95 + pd_idx = data_disks;
96 + qd_idx = data_disks + 1;
97 + break;
98 +
99 + case ALGORITHM_ROTATING_ZERO_RESTART:
100 + /* Exactly the same as RIGHT_ASYMMETRIC, but or
101 + * of blocks for computing Q is different.
102 + */
103 + pd_idx = stripe % raid_disks;
104 + qd_idx = pd_idx + 1;
105 + if (pd_idx == raid_disks-1) {
106 + (*dd_idx)++; /* Q D D D P */
107 + qd_idx = 0;
108 + } else if (*dd_idx >= pd_idx)
109 + (*dd_idx) += 2; /* D D P Q D */
110 + break;
111 +
112 + case ALGORITHM_ROTATING_N_RESTART:
113 + /* Same a left_asymmetric, by first stripe is
114 + * D D D P Q rather than
115 + * Q D D D P
116 + */
117 + pd_idx = raid_disks - 1 - ((stripe + 1) % raid_disks);
118 + qd_idx = pd_idx + 1;
119 + if (pd_idx == raid_disks-1) {
120 + (*dd_idx)++; /* Q D D D P */
121 + qd_idx = 0;
122 + } else if (*dd_idx >= pd_idx)
123 + (*dd_idx) += 2; /* D D P Q D */
124 + break;
125 +
126 + case ALGORITHM_ROTATING_N_CONTINUE:
127 + /* Same as left_symmetric but Q is before P */
128 + pd_idx = raid_disks - 1 - (stripe % raid_disks);
129 + qd_idx = (pd_idx + raid_disks - 1) % raid_disks;
130 + *dd_idx = (pd_idx + 1 + *dd_idx) % raid_disks;
131 + break;
132 +
133 + case ALGORITHM_LEFT_ASYMMETRIC_6:
134 + /* RAID5 left_asymmetric, with Q on last device */
135 + pd_idx = data_disks - stripe % (raid_disks-1);
136 + if (*dd_idx >= pd_idx)
137 + (*dd_idx)++;
138 + qd_idx = raid_disks - 1;
139 + break;
140 +
141 + case ALGORITHM_RIGHT_ASYMMETRIC_6:
142 + pd_idx = stripe % (raid_disks-1);
143 + if (*dd_idx >= pd_idx)
144 + (*dd_idx)++;
145 + qd_idx = raid_disks - 1;
146 + break;
147 +
148 + case ALGORITHM_LEFT_SYMMETRIC_6:
149 + pd_idx = data_disks - stripe % (raid_disks-1);
150 + *dd_idx = (pd_idx + 1 + *dd_idx) % (raid_disks-1);
151 + qd_idx = raid_disks - 1;
152 + break;
153 +
154 + case ALGORITHM_RIGHT_SYMMETRIC_6:
155 + pd_idx = stripe % (raid_disks-1);
156 + *dd_idx = (pd_idx + 1 + *dd_idx) % (raid_disks-1);
157 + qd_idx = raid_disks - 1;
158 + break;
159 +
160 + case ALGORITHM_PARITY_0_6:
161 + pd_idx = 0;
162 + (*dd_idx)++;
163 + qd_idx = raid_disks - 1;
164 + break;
165 +
166 +
167 default:
168 printk (KERN_CRIT "raid6: unsupported algorithm %d\n",
169 conf->algorithm);
170 + BUG();
171 }
172 break;
173 }
174 @@ -1413,9 +1500,15 @@ static sector_t compute_blocknr(struct s
175 i += raid_disks;
176 i -= (sh->pd_idx + 1);
177 break;
178 + case ALGORITHM_PARITY_0:
179 + i -= 1;
180 + break;
181 + case ALGORITHM_PARITY_N:
182 + break;
183 default:
184 printk(KERN_ERR "raid5: unsupported algorithm %d\n",
185 conf->algorithm);
186 + BUG();
187 }
188 break;
189 case 6:
190 @@ -1424,8 +1517,10 @@ static sector_t compute_blocknr(struct s
191 switch (conf->algorithm) {
192 case ALGORITHM_LEFT_ASYMMETRIC:
193 case ALGORITHM_RIGHT_ASYMMETRIC:
194 - if (sh->pd_idx == raid_disks-1)
195 - i--; /* Q D D D P */
196 + case ALGORITHM_ROTATING_ZERO_RESTART:
197 + case ALGORITHM_ROTATING_N_RESTART:
198 + if (sh->pd_idx == raid_disks-1)
199 + i--; /* Q D D D P */
200 else if (i > sh->pd_idx)
201 i -= 2; /* D D P Q D */
202 break;
203 @@ -1440,9 +1535,35 @@ static sector_t compute_blocknr(struct s
204 i -= (sh->pd_idx + 2);
205 }
206 break;
207 + case ALGORITHM_PARITY_0:
208 + i -= 2;
209 + break;
210 + case ALGORITHM_PARITY_N:
211 + break;
212 + case ALGORITHM_ROTATING_N_CONTINUE:
213 + if (sh->pd_idx == 0)
214 + i--; /* P D D D Q */
215 + else if (i > sh->pd_idx)
216 + i -= 2; /* D D Q P D */
217 + break;
218 + case ALGORITHM_LEFT_ASYMMETRIC_6:
219 + case ALGORITHM_RIGHT_ASYMMETRIC_6:
220 + if (i > sh->pd_idx)
221 + i--;
222 + break;
223 + case ALGORITHM_LEFT_SYMMETRIC_6:
224 + case ALGORITHM_RIGHT_SYMMETRIC_6:
225 + if (i < sh->pd_idx)
226 + i += data_disks + 1;
227 + i -= (sh->pd_idx + 1);
228 + break;
229 + case ALGORITHM_PARITY_0_6:
230 + i -= 1;
231 + break;
232 default:
233 printk (KERN_CRIT "raid6: unsupported algorithm %d\n",
234 conf->algorithm);
235 + BUG();
236 }
237 break;
238 }
239 @@ -3310,7 +3431,7 @@ static int chunk_aligned_read(struct req
240 return 0;
241 }
242 /*
243 - * use bio_clone to make a copy of the bio
244 + * use bio_clone to make a copy of the bio
245 */
246 align_bi = bio_clone(raid_bio, GFP_NOIO);
247 if (!align_bi)
248 @@ -3438,7 +3559,7 @@ static int make_request(struct request_q
249 if (rw == READ &&
250 mddev->reshape_position == MaxSector &&
251 chunk_aligned_read(q,bi))
252 - return 0;
253 + return 0;
254
255 logical_sector = bi->bi_sector & ~((sector_t)STRIPE_SECTORS-1);
256 last_sector = bi->bi_sector + (bi->bi_size>>9);
257 @@ -4035,6 +4156,12 @@ static int run(mddev_t *mddev)
258 mdname(mddev), mddev->level);
259 return -EIO;
260 }
261 + if ((mddev->level == 5 && !algorithm_valid_raid5(mddev->layout)) ||
262 + (mddev->level == 6 && !algorithm_valid_raid6(mddev->layout))) {
263 + printk(KERN_ERR "raid5: %s: layout %d not supported\n",
264 + mdname(mddev), mddev->layout);
265 + return -EIO;
266 + }
267
268 if (mddev->chunk_size < PAGE_SIZE) {
269 printk(KERN_ERR "md/raid5: chunk_size must be at least "
270 @@ -4186,12 +4313,6 @@ static int run(mddev_t *mddev)
271 conf->chunk_size, mdname(mddev));
272 goto abort;
273 }
274 - if (conf->algorithm > ALGORITHM_RIGHT_SYMMETRIC) {
275 - printk(KERN_ERR
276 - "raid5: unsupported parity algorithm %d for %s\n",
277 - conf->algorithm, mdname(mddev));
278 - goto abort;
279 - }
280 if (mddev->degraded > conf->max_degraded) {
281 printk(KERN_ERR "raid5: not enough operational devices for %s"
282 " (%d/%d failed)\n",
283 --- linux-2.6.27-SLE11_BRANCH.orig/include/linux/raid/raid5.h
284 +++ linux-2.6.27-SLE11_BRANCH/include/linux/raid/raid5.h
285 @@ -395,9 +395,62 @@ typedef struct raid5_private_data raid5_
286 /*
287 * Our supported algorithms
288 */
289 -#define ALGORITHM_LEFT_ASYMMETRIC 0
290 -#define ALGORITHM_RIGHT_ASYMMETRIC 1
291 -#define ALGORITHM_LEFT_SYMMETRIC 2
292 -#define ALGORITHM_RIGHT_SYMMETRIC 3
293 +#define ALGORITHM_LEFT_ASYMMETRIC 0 /* Rotating Parity N with Data Restart */
294 +#define ALGORITHM_RIGHT_ASYMMETRIC 1 /* Rotating Parity 0 with Data Restart */
295 +#define ALGORITHM_LEFT_SYMMETRIC 2 /* Rotating Parity N with Data Continuation */
296 +#define ALGORITHM_RIGHT_SYMMETRIC 3 /* Rotating Parity 0 with Data Continuation */
297
298 +/* Define non-rotating (raid4) algorithms. These allow
299 + * conversion of raid4 to raid5.
300 + */
301 +#define ALGORITHM_PARITY_0 4 /* P or P,Q are initial devices */
302 +#define ALGORITHM_PARITY_N 5 /* P or P,Q are final devices. */
303 +
304 +/* DDF RAID6 layouts differ from md/raid6 layouts in two ways.
305 + * Firstly, the exact positioning of the parity block is slightly
306 + * different between the 'LEFT_*' modes of md and the "_N_*" modes
307 + * of DDF.
308 + * Secondly, or order of datablocks over which the Q syndrome is computed
309 + * is different.
310 + * Consequently we have different layouts for DDF/raid6 than md/raid6.
311 + * These layouts are from the DDFv1.2 spec.
312 + * Interestingly DDFv1.2-Errata-A does not specify N_CONTINUE but
313 + * leaves RLQ=3 as 'Vendor Specific'
314 + */
315 +
316 +#define ALGORITHM_ROTATING_ZERO_RESTART 8 /* DDF PRL=6 RLQ=1 */
317 +#define ALGORITHM_ROTATING_N_RESTART 9 /* DDF PRL=6 RLQ=2 */
318 +#define ALGORITHM_ROTATING_N_CONTINUE 10 /*DDF PRL=6 RLQ=3 */
319 +
320 +
321 +/* For every RAID5 algorithm we define a RAID6 algorithm
322 + * with exactly the same layout for data and parity, and
323 + * with the Q block always on the last device (N-1).
324 + * This allows trivial conversion from RAID5 to RAID6
325 + */
326 +#define ALGORITHM_LEFT_ASYMMETRIC_6 16
327 +#define ALGORITHM_RIGHT_ASYMMETRIC_6 17
328 +#define ALGORITHM_LEFT_SYMMETRIC_6 18
329 +#define ALGORITHM_RIGHT_SYMMETRIC_6 19
330 +#define ALGORITHM_PARITY_0_6 20
331 +#define ALGORITHM_PARITY_N_6 ALGORITHM_PARITY_N
332 +
333 +static inline int algorithm_valid_raid5(int layout)
334 +{
335 + return (layout >= 0) &&
336 + (layout <= 5);
337 +}
338 +static inline int algorithm_valid_raid6(int layout)
339 +{
340 + return (layout >= 0 && layout <= 5)
341 + ||
342 + (layout == 8 || layout == 10)
343 + ||
344 + (layout >= 16 && layout <= 20);
345 +}
346 +
347 +static inline int algorithm_is_DDF(int layout)
348 +{
349 + return layout >= 8 && layout <= 10;
350 +}
351 #endif