diff options
author | NeilBrown <neilb@suse.de> | 2011-12-22 18:17:54 -0500 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2011-12-22 18:17:54 -0500 |
commit | 69335ef3bc5b766f34db2d688be1d35313138bca (patch) | |
tree | dcd87ffc4c97540d374a20de7380368e3679ac3b /drivers/md/raid10.c | |
parent | 3a6de2924af602f9c1b5a5154438c37f2d712dfa (diff) |
md/raid10: prepare data structures for handling replacement.
Allow each slot in the RAID10 to have 2 devices, the want_replacement
and the replacement.
Also an r10bio to have 2 bios, and for resync/recovery allocate the
second bio if there are any replacement devices.
Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'drivers/md/raid10.c')
-rw-r--r-- | drivers/md/raid10.c | 48 |
1 files changed, 41 insertions, 7 deletions
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index f5088dda4dca..9722065022fa 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c | |||
@@ -73,7 +73,8 @@ static void * r10bio_pool_alloc(gfp_t gfp_flags, void *data) | |||
73 | struct r10conf *conf = data; | 73 | struct r10conf *conf = data; |
74 | int size = offsetof(struct r10bio, devs[conf->copies]); | 74 | int size = offsetof(struct r10bio, devs[conf->copies]); |
75 | 75 | ||
76 | /* allocate a r10bio with room for raid_disks entries in the bios array */ | 76 | /* allocate a r10bio with room for raid_disks entries in the |
77 | * bios array */ | ||
77 | return kzalloc(size, gfp_flags); | 78 | return kzalloc(size, gfp_flags); |
78 | } | 79 | } |
79 | 80 | ||
@@ -123,12 +124,19 @@ static void * r10buf_pool_alloc(gfp_t gfp_flags, void *data) | |||
123 | if (!bio) | 124 | if (!bio) |
124 | goto out_free_bio; | 125 | goto out_free_bio; |
125 | r10_bio->devs[j].bio = bio; | 126 | r10_bio->devs[j].bio = bio; |
127 | if (!conf->have_replacement) | ||
128 | continue; | ||
129 | bio = bio_kmalloc(gfp_flags, RESYNC_PAGES); | ||
130 | if (!bio) | ||
131 | goto out_free_bio; | ||
132 | r10_bio->devs[j].repl_bio = bio; | ||
126 | } | 133 | } |
127 | /* | 134 | /* |
128 | * Allocate RESYNC_PAGES data pages and attach them | 135 | * Allocate RESYNC_PAGES data pages and attach them |
129 | * where needed. | 136 | * where needed. |
130 | */ | 137 | */ |
131 | for (j = 0 ; j < nalloc; j++) { | 138 | for (j = 0 ; j < nalloc; j++) { |
139 | struct bio *rbio = r10_bio->devs[j].repl_bio; | ||
132 | bio = r10_bio->devs[j].bio; | 140 | bio = r10_bio->devs[j].bio; |
133 | for (i = 0; i < RESYNC_PAGES; i++) { | 141 | for (i = 0; i < RESYNC_PAGES; i++) { |
134 | if (j == 1 && !test_bit(MD_RECOVERY_SYNC, | 142 | if (j == 1 && !test_bit(MD_RECOVERY_SYNC, |
@@ -143,6 +151,8 @@ static void * r10buf_pool_alloc(gfp_t gfp_flags, void *data) | |||
143 | goto out_free_pages; | 151 | goto out_free_pages; |
144 | 152 | ||
145 | bio->bi_io_vec[i].bv_page = page; | 153 | bio->bi_io_vec[i].bv_page = page; |
154 | if (rbio) | ||
155 | rbio->bi_io_vec[i].bv_page = page; | ||
146 | } | 156 | } |
147 | } | 157 | } |
148 | 158 | ||
@@ -156,8 +166,11 @@ out_free_pages: | |||
156 | safe_put_page(r10_bio->devs[j].bio->bi_io_vec[i].bv_page); | 166 | safe_put_page(r10_bio->devs[j].bio->bi_io_vec[i].bv_page); |
157 | j = -1; | 167 | j = -1; |
158 | out_free_bio: | 168 | out_free_bio: |
159 | while ( ++j < nalloc ) | 169 | while (++j < nalloc) { |
160 | bio_put(r10_bio->devs[j].bio); | 170 | bio_put(r10_bio->devs[j].bio); |
171 | if (r10_bio->devs[j].repl_bio) | ||
172 | bio_put(r10_bio->devs[j].repl_bio); | ||
173 | } | ||
161 | r10bio_pool_free(r10_bio, conf); | 174 | r10bio_pool_free(r10_bio, conf); |
162 | return NULL; | 175 | return NULL; |
163 | } | 176 | } |
@@ -178,6 +191,9 @@ static void r10buf_pool_free(void *__r10_bio, void *data) | |||
178 | } | 191 | } |
179 | bio_put(bio); | 192 | bio_put(bio); |
180 | } | 193 | } |
194 | bio = r10bio->devs[j].repl_bio; | ||
195 | if (bio) | ||
196 | bio_put(bio); | ||
181 | } | 197 | } |
182 | r10bio_pool_free(r10bio, conf); | 198 | r10bio_pool_free(r10bio, conf); |
183 | } | 199 | } |
@@ -191,6 +207,10 @@ static void put_all_bios(struct r10conf *conf, struct r10bio *r10_bio) | |||
191 | if (!BIO_SPECIAL(*bio)) | 207 | if (!BIO_SPECIAL(*bio)) |
192 | bio_put(*bio); | 208 | bio_put(*bio); |
193 | *bio = NULL; | 209 | *bio = NULL; |
210 | bio = &r10_bio->devs[i].repl_bio; | ||
211 | if (r10_bio->read_slot < 0 && !BIO_SPECIAL(*bio)) | ||
212 | bio_put(*bio); | ||
213 | *bio = NULL; | ||
194 | } | 214 | } |
195 | } | 215 | } |
196 | 216 | ||
@@ -275,19 +295,27 @@ static inline void update_head_pos(int slot, struct r10bio *r10_bio) | |||
275 | * Find the disk number which triggered given bio | 295 | * Find the disk number which triggered given bio |
276 | */ | 296 | */ |
277 | static int find_bio_disk(struct r10conf *conf, struct r10bio *r10_bio, | 297 | static int find_bio_disk(struct r10conf *conf, struct r10bio *r10_bio, |
278 | struct bio *bio, int *slotp) | 298 | struct bio *bio, int *slotp, int *replp) |
279 | { | 299 | { |
280 | int slot; | 300 | int slot; |
301 | int repl = 0; | ||
281 | 302 | ||
282 | for (slot = 0; slot < conf->copies; slot++) | 303 | for (slot = 0; slot < conf->copies; slot++) { |
283 | if (r10_bio->devs[slot].bio == bio) | 304 | if (r10_bio->devs[slot].bio == bio) |
284 | break; | 305 | break; |
306 | if (r10_bio->devs[slot].repl_bio == bio) { | ||
307 | repl = 1; | ||
308 | break; | ||
309 | } | ||
310 | } | ||
285 | 311 | ||
286 | BUG_ON(slot == conf->copies); | 312 | BUG_ON(slot == conf->copies); |
287 | update_head_pos(slot, r10_bio); | 313 | update_head_pos(slot, r10_bio); |
288 | 314 | ||
289 | if (slotp) | 315 | if (slotp) |
290 | *slotp = slot; | 316 | *slotp = slot; |
317 | if (replp) | ||
318 | *replp = repl; | ||
291 | return r10_bio->devs[slot].devnum; | 319 | return r10_bio->devs[slot].devnum; |
292 | } | 320 | } |
293 | 321 | ||
@@ -368,7 +396,7 @@ static void raid10_end_write_request(struct bio *bio, int error) | |||
368 | struct r10conf *conf = r10_bio->mddev->private; | 396 | struct r10conf *conf = r10_bio->mddev->private; |
369 | int slot; | 397 | int slot; |
370 | 398 | ||
371 | dev = find_bio_disk(conf, r10_bio, bio, &slot); | 399 | dev = find_bio_disk(conf, r10_bio, bio, &slot, NULL); |
372 | 400 | ||
373 | /* | 401 | /* |
374 | * this branch is our 'one mirror IO has finished' event handler: | 402 | * this branch is our 'one mirror IO has finished' event handler: |
@@ -1025,6 +1053,7 @@ read_again: | |||
1025 | */ | 1053 | */ |
1026 | plugged = mddev_check_plugged(mddev); | 1054 | plugged = mddev_check_plugged(mddev); |
1027 | 1055 | ||
1056 | r10_bio->read_slot = -1; /* make sure repl_bio gets freed */ | ||
1028 | raid10_find_phys(conf, r10_bio); | 1057 | raid10_find_phys(conf, r10_bio); |
1029 | retry_write: | 1058 | retry_write: |
1030 | blocked_rdev = NULL; | 1059 | blocked_rdev = NULL; |
@@ -1431,7 +1460,7 @@ static void end_sync_read(struct bio *bio, int error) | |||
1431 | struct r10conf *conf = r10_bio->mddev->private; | 1460 | struct r10conf *conf = r10_bio->mddev->private; |
1432 | int d; | 1461 | int d; |
1433 | 1462 | ||
1434 | d = find_bio_disk(conf, r10_bio, bio, NULL); | 1463 | d = find_bio_disk(conf, r10_bio, bio, NULL, NULL); |
1435 | 1464 | ||
1436 | if (test_bit(BIO_UPTODATE, &bio->bi_flags)) | 1465 | if (test_bit(BIO_UPTODATE, &bio->bi_flags)) |
1437 | set_bit(R10BIO_Uptodate, &r10_bio->state); | 1466 | set_bit(R10BIO_Uptodate, &r10_bio->state); |
@@ -1493,7 +1522,7 @@ static void end_sync_write(struct bio *bio, int error) | |||
1493 | int bad_sectors; | 1522 | int bad_sectors; |
1494 | int slot; | 1523 | int slot; |
1495 | 1524 | ||
1496 | d = find_bio_disk(conf, r10_bio, bio, &slot); | 1525 | d = find_bio_disk(conf, r10_bio, bio, &slot, NULL); |
1497 | 1526 | ||
1498 | if (!uptodate) { | 1527 | if (!uptodate) { |
1499 | set_bit(WriteErrorSeen, &conf->mirrors[d].rdev->flags); | 1528 | set_bit(WriteErrorSeen, &conf->mirrors[d].rdev->flags); |
@@ -2271,9 +2300,14 @@ static void raid10d(struct mddev *mddev) | |||
2271 | static int init_resync(struct r10conf *conf) | 2300 | static int init_resync(struct r10conf *conf) |
2272 | { | 2301 | { |
2273 | int buffs; | 2302 | int buffs; |
2303 | int i; | ||
2274 | 2304 | ||
2275 | buffs = RESYNC_WINDOW / RESYNC_BLOCK_SIZE; | 2305 | buffs = RESYNC_WINDOW / RESYNC_BLOCK_SIZE; |
2276 | BUG_ON(conf->r10buf_pool); | 2306 | BUG_ON(conf->r10buf_pool); |
2307 | conf->have_replacement = 0; | ||
2308 | for (i = 0; i < conf->raid_disks; i++) | ||
2309 | if (conf->mirrors[i].replacement) | ||
2310 | conf->have_replacement = 1; | ||
2277 | conf->r10buf_pool = mempool_create(buffs, r10buf_pool_alloc, r10buf_pool_free, conf); | 2311 | conf->r10buf_pool = mempool_create(buffs, r10buf_pool_alloc, r10buf_pool_free, conf); |
2278 | if (!conf->r10buf_pool) | 2312 | if (!conf->r10buf_pool) |
2279 | return -ENOMEM; | 2313 | return -ENOMEM; |