Skip to content

Commit 24afd80

Browse files
committed
md/raid10: handle recovery of replacement devices.
If there is a replacement device, then recover to it, reading from any drives - maybe the one being replaced, maybe not. Signed-off-by: NeilBrown <[email protected]>
1 parent 9ad1aef commit 24afd80

File tree

1 file changed

+80
-30
lines changed

1 file changed

+80
-30
lines changed

drivers/md/raid10.c

Lines changed: 80 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1843,7 +1843,7 @@ static void recovery_request_write(struct mddev *mddev, struct r10bio *r10_bio)
18431843
{
18441844
struct r10conf *conf = mddev->private;
18451845
int d;
1846-
struct bio *wbio;
1846+
struct bio *wbio, *wbio2;
18471847

18481848
if (!test_bit(R10BIO_Uptodate, &r10_bio->state)) {
18491849
fix_recovery_read_error(r10_bio);
@@ -1855,12 +1855,20 @@ static void recovery_request_write(struct mddev *mddev, struct r10bio *r10_bio)
18551855
* share the pages with the first bio
18561856
* and submit the write request
18571857
*/
1858-
wbio = r10_bio->devs[1].bio;
18591858
d = r10_bio->devs[1].devnum;
1860-
1861-
atomic_inc(&conf->mirrors[d].rdev->nr_pending);
1862-
md_sync_acct(conf->mirrors[d].rdev->bdev, wbio->bi_size >> 9);
1863-
generic_make_request(wbio);
1859+
wbio = r10_bio->devs[1].bio;
1860+
wbio2 = r10_bio->devs[1].repl_bio;
1861+
if (wbio->bi_end_io) {
1862+
atomic_inc(&conf->mirrors[d].rdev->nr_pending);
1863+
md_sync_acct(conf->mirrors[d].rdev->bdev, wbio->bi_size >> 9);
1864+
generic_make_request(wbio);
1865+
}
1866+
if (wbio2 && wbio2->bi_end_io) {
1867+
atomic_inc(&conf->mirrors[d].replacement->nr_pending);
1868+
md_sync_acct(conf->mirrors[d].replacement->bdev,
1869+
wbio2->bi_size >> 9);
1870+
generic_make_request(wbio2);
1871+
}
18641872
}
18651873

18661874

@@ -2590,23 +2598,30 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr,
25902598
sector_t sect;
25912599
int must_sync;
25922600
int any_working;
2593-
2594-
if (conf->mirrors[i].rdev == NULL ||
2595-
test_bit(In_sync, &conf->mirrors[i].rdev->flags))
2601+
struct mirror_info *mirror = &conf->mirrors[i];
2602+
2603+
if ((mirror->rdev == NULL ||
2604+
test_bit(In_sync, &mirror->rdev->flags))
2605+
&&
2606+
(mirror->replacement == NULL ||
2607+
test_bit(Faulty,
2608+
&mirror->replacement->flags)))
25962609
continue;
25972610

25982611
still_degraded = 0;
25992612
/* want to reconstruct this device */
26002613
rb2 = r10_bio;
26012614
sect = raid10_find_virt(conf, sector_nr, i);
2602-
/* Unless we are doing a full sync, we only need
2603-
* to recover the block if it is set in the bitmap
2615+
/* Unless we are doing a full sync, or a replacement
2616+
* we only need to recover the block if it is set in
2617+
* the bitmap
26042618
*/
26052619
must_sync = bitmap_start_sync(mddev->bitmap, sect,
26062620
&sync_blocks, 1);
26072621
if (sync_blocks < max_sync)
26082622
max_sync = sync_blocks;
26092623
if (!must_sync &&
2624+
mirror->replacement == NULL &&
26102625
!conf->fullsync) {
26112626
/* yep, skip the sync_blocks here, but don't assume
26122627
* that there will never be anything to do here
@@ -2676,33 +2691,60 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr,
26762691
bio->bi_end_io = end_sync_read;
26772692
bio->bi_rw = READ;
26782693
from_addr = r10_bio->devs[j].addr;
2679-
bio->bi_sector = from_addr +
2680-
conf->mirrors[d].rdev->data_offset;
2681-
bio->bi_bdev = conf->mirrors[d].rdev->bdev;
2682-
atomic_inc(&conf->mirrors[d].rdev->nr_pending);
2683-
atomic_inc(&r10_bio->remaining);
2684-
/* and we write to 'i' */
2694+
bio->bi_sector = from_addr + rdev->data_offset;
2695+
bio->bi_bdev = rdev->bdev;
2696+
atomic_inc(&rdev->nr_pending);
2697+
/* and we write to 'i' (if not in_sync) */
26852698

26862699
for (k=0; k<conf->copies; k++)
26872700
if (r10_bio->devs[k].devnum == i)
26882701
break;
26892702
BUG_ON(k == conf->copies);
2690-
bio = r10_bio->devs[1].bio;
2691-
bio->bi_next = biolist;
2692-
biolist = bio;
2693-
bio->bi_private = r10_bio;
2694-
bio->bi_end_io = end_sync_write;
2695-
bio->bi_rw = WRITE;
26962703
to_addr = r10_bio->devs[k].addr;
2697-
bio->bi_sector = to_addr +
2698-
conf->mirrors[i].rdev->data_offset;
2699-
bio->bi_bdev = conf->mirrors[i].rdev->bdev;
2700-
27012704
r10_bio->devs[0].devnum = d;
27022705
r10_bio->devs[0].addr = from_addr;
27032706
r10_bio->devs[1].devnum = i;
27042707
r10_bio->devs[1].addr = to_addr;
27052708

2709+
rdev = mirror->rdev;
2710+
if (!test_bit(In_sync, &rdev->flags)) {
2711+
bio = r10_bio->devs[1].bio;
2712+
bio->bi_next = biolist;
2713+
biolist = bio;
2714+
bio->bi_private = r10_bio;
2715+
bio->bi_end_io = end_sync_write;
2716+
bio->bi_rw = WRITE;
2717+
bio->bi_sector = to_addr
2718+
+ rdev->data_offset;
2719+
bio->bi_bdev = rdev->bdev;
2720+
atomic_inc(&r10_bio->remaining);
2721+
} else
2722+
r10_bio->devs[1].bio->bi_end_io = NULL;
2723+
2724+
/* and maybe write to replacement */
2725+
bio = r10_bio->devs[1].repl_bio;
2726+
if (bio)
2727+
bio->bi_end_io = NULL;
2728+
rdev = mirror->replacement;
2729+
/* Note: if rdev != NULL, then bio
2730+
* cannot be NULL as r10buf_pool_alloc will
2731+
* have allocated it.
2732+
* So the second test here is pointless.
2733+
* But it keeps semantic-checkers happy, and
2734+
* this comment keeps human reviewers
2735+
* happy.
2736+
*/
2737+
if (rdev == NULL || bio == NULL ||
2738+
test_bit(Faulty, &rdev->flags))
2739+
break;
2740+
bio->bi_next = biolist;
2741+
biolist = bio;
2742+
bio->bi_private = r10_bio;
2743+
bio->bi_end_io = end_sync_write;
2744+
bio->bi_rw = WRITE;
2745+
bio->bi_sector = to_addr + rdev->data_offset;
2746+
bio->bi_bdev = rdev->bdev;
2747+
atomic_inc(&r10_bio->remaining);
27062748
break;
27072749
}
27082750
if (j == conf->copies) {
@@ -2720,8 +2762,16 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr,
27202762
for (k = 0; k < conf->copies; k++)
27212763
if (r10_bio->devs[k].devnum == i)
27222764
break;
2723-
if (!rdev_set_badblocks(
2724-
conf->mirrors[i].rdev,
2765+
if (!test_bit(In_sync,
2766+
&mirror->rdev->flags)
2767+
&& !rdev_set_badblocks(
2768+
mirror->rdev,
2769+
r10_bio->devs[k].addr,
2770+
max_sync, 0))
2771+
any_working = 0;
2772+
if (mirror->replacement &&
2773+
!rdev_set_badblocks(
2774+
mirror->replacement,
27252775
r10_bio->devs[k].addr,
27262776
max_sync, 0))
27272777
any_working = 0;
@@ -2732,7 +2782,7 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr,
27322782
printk(KERN_INFO "md/raid10:%s: insufficient "
27332783
"working devices for recovery.\n",
27342784
mdname(mddev));
2735-
conf->mirrors[i].recovery_disabled
2785+
mirror->recovery_disabled
27362786
= mddev->recovery_disabled;
27372787
}
27382788
break;

0 commit comments

Comments
 (0)