md/raid10: Handle replacement devices during resync.
If we need to resync an array which has replacement devices, we always write any block checked to every replacement. If the resync was bitmap-based resync we will then complete the replacement normally. If it was a full resync, we mark the replacements as fully recovered when the resync finishes so no further recovery is needed. Signed-off-by: NeilBrown <neilb@suse.de>
This commit is contained in:
Родитель
475b0321a4
Коммит
9ad1aefc8a
|
@ -1594,19 +1594,29 @@ static void end_sync_write(struct bio *bio, int error)
|
||||||
sector_t first_bad;
|
sector_t first_bad;
|
||||||
int bad_sectors;
|
int bad_sectors;
|
||||||
int slot;
|
int slot;
|
||||||
|
int repl;
|
||||||
|
struct md_rdev *rdev;
|
||||||
|
|
||||||
d = find_bio_disk(conf, r10_bio, bio, &slot, NULL);
|
d = find_bio_disk(conf, r10_bio, bio, &slot, &repl);
|
||||||
|
if (repl)
|
||||||
|
rdev = conf->mirrors[d].replacement;
|
||||||
|
else
|
||||||
|
rdev = conf->mirrors[d].rdev;
|
||||||
|
|
||||||
if (!uptodate) {
|
if (!uptodate) {
|
||||||
set_bit(WriteErrorSeen, &conf->mirrors[d].rdev->flags);
|
if (repl)
|
||||||
|
md_error(mddev, rdev);
|
||||||
|
else {
|
||||||
|
set_bit(WriteErrorSeen, &rdev->flags);
|
||||||
set_bit(R10BIO_WriteError, &r10_bio->state);
|
set_bit(R10BIO_WriteError, &r10_bio->state);
|
||||||
} else if (is_badblock(conf->mirrors[d].rdev,
|
}
|
||||||
|
} else if (is_badblock(rdev,
|
||||||
r10_bio->devs[slot].addr,
|
r10_bio->devs[slot].addr,
|
||||||
r10_bio->sectors,
|
r10_bio->sectors,
|
||||||
&first_bad, &bad_sectors))
|
&first_bad, &bad_sectors))
|
||||||
set_bit(R10BIO_MadeGood, &r10_bio->state);
|
set_bit(R10BIO_MadeGood, &r10_bio->state);
|
||||||
|
|
||||||
rdev_dec_pending(conf->mirrors[d].rdev, mddev);
|
rdev_dec_pending(rdev, mddev);
|
||||||
|
|
||||||
end_sync_request(r10_bio);
|
end_sync_request(r10_bio);
|
||||||
}
|
}
|
||||||
|
@ -1710,6 +1720,29 @@ static void sync_request_write(struct mddev *mddev, struct r10bio *r10_bio)
|
||||||
generic_make_request(tbio);
|
generic_make_request(tbio);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Now write out to any replacement devices
|
||||||
|
* that are active
|
||||||
|
*/
|
||||||
|
for (i = 0; i < conf->copies; i++) {
|
||||||
|
int j, d;
|
||||||
|
int vcnt = r10_bio->sectors >> (PAGE_SHIFT-9);
|
||||||
|
|
||||||
|
tbio = r10_bio->devs[i].repl_bio;
|
||||||
|
if (!tbio || !tbio->bi_end_io)
|
||||||
|
continue;
|
||||||
|
if (r10_bio->devs[i].bio->bi_end_io != end_sync_write
|
||||||
|
&& r10_bio->devs[i].bio != fbio)
|
||||||
|
for (j = 0; j < vcnt; j++)
|
||||||
|
memcpy(page_address(tbio->bi_io_vec[j].bv_page),
|
||||||
|
page_address(fbio->bi_io_vec[j].bv_page),
|
||||||
|
PAGE_SIZE);
|
||||||
|
d = r10_bio->devs[i].devnum;
|
||||||
|
atomic_inc(&r10_bio->remaining);
|
||||||
|
md_sync_acct(conf->mirrors[d].replacement->bdev,
|
||||||
|
tbio->bi_size >> 9);
|
||||||
|
generic_make_request(tbio);
|
||||||
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
if (atomic_dec_and_test(&r10_bio->remaining)) {
|
if (atomic_dec_and_test(&r10_bio->remaining)) {
|
||||||
md_done_sync(mddev, r10_bio->sectors, 1);
|
md_done_sync(mddev, r10_bio->sectors, 1);
|
||||||
|
@ -2287,6 +2320,22 @@ static void handle_write_completed(struct r10conf *conf, struct r10bio *r10_bio)
|
||||||
r10_bio->sectors, 0))
|
r10_bio->sectors, 0))
|
||||||
md_error(conf->mddev, rdev);
|
md_error(conf->mddev, rdev);
|
||||||
}
|
}
|
||||||
|
rdev = conf->mirrors[dev].replacement;
|
||||||
|
if (r10_bio->devs[m].repl_bio == NULL)
|
||||||
|
continue;
|
||||||
|
if (test_bit(BIO_UPTODATE,
|
||||||
|
&r10_bio->devs[m].repl_bio->bi_flags)) {
|
||||||
|
rdev_clear_badblocks(
|
||||||
|
rdev,
|
||||||
|
r10_bio->devs[m].addr,
|
||||||
|
r10_bio->sectors);
|
||||||
|
} else {
|
||||||
|
if (!rdev_set_badblocks(
|
||||||
|
rdev,
|
||||||
|
r10_bio->devs[m].addr,
|
||||||
|
r10_bio->sectors, 0))
|
||||||
|
md_error(conf->mddev, rdev);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
put_buf(r10_bio);
|
put_buf(r10_bio);
|
||||||
} else {
|
} else {
|
||||||
|
@ -2469,9 +2518,22 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr,
|
||||||
bitmap_end_sync(mddev->bitmap, sect,
|
bitmap_end_sync(mddev->bitmap, sect,
|
||||||
&sync_blocks, 1);
|
&sync_blocks, 1);
|
||||||
}
|
}
|
||||||
} else /* completed sync */
|
} else {
|
||||||
|
/* completed sync */
|
||||||
|
if ((!mddev->bitmap || conf->fullsync)
|
||||||
|
&& conf->have_replacement
|
||||||
|
&& test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) {
|
||||||
|
/* Completed a full sync so the replacements
|
||||||
|
* are now fully recovered.
|
||||||
|
*/
|
||||||
|
for (i = 0; i < conf->raid_disks; i++)
|
||||||
|
if (conf->mirrors[i].replacement)
|
||||||
|
conf->mirrors[i].replacement
|
||||||
|
->recovery_offset
|
||||||
|
= MaxSector;
|
||||||
|
}
|
||||||
conf->fullsync = 0;
|
conf->fullsync = 0;
|
||||||
|
}
|
||||||
bitmap_close_sync(mddev->bitmap);
|
bitmap_close_sync(mddev->bitmap);
|
||||||
close_sync(conf);
|
close_sync(conf);
|
||||||
*skipped = 1;
|
*skipped = 1;
|
||||||
|
@ -2719,6 +2781,9 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr,
|
||||||
sector_t first_bad, sector;
|
sector_t first_bad, sector;
|
||||||
int bad_sectors;
|
int bad_sectors;
|
||||||
|
|
||||||
|
if (r10_bio->devs[i].repl_bio)
|
||||||
|
r10_bio->devs[i].repl_bio->bi_end_io = NULL;
|
||||||
|
|
||||||
bio = r10_bio->devs[i].bio;
|
bio = r10_bio->devs[i].bio;
|
||||||
bio->bi_end_io = NULL;
|
bio->bi_end_io = NULL;
|
||||||
clear_bit(BIO_UPTODATE, &bio->bi_flags);
|
clear_bit(BIO_UPTODATE, &bio->bi_flags);
|
||||||
|
@ -2749,6 +2814,27 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr,
|
||||||
conf->mirrors[d].rdev->data_offset;
|
conf->mirrors[d].rdev->data_offset;
|
||||||
bio->bi_bdev = conf->mirrors[d].rdev->bdev;
|
bio->bi_bdev = conf->mirrors[d].rdev->bdev;
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
|
if (conf->mirrors[d].replacement == NULL ||
|
||||||
|
test_bit(Faulty,
|
||||||
|
&conf->mirrors[d].replacement->flags))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Need to set up for writing to the replacement */
|
||||||
|
bio = r10_bio->devs[i].repl_bio;
|
||||||
|
clear_bit(BIO_UPTODATE, &bio->bi_flags);
|
||||||
|
|
||||||
|
sector = r10_bio->devs[i].addr;
|
||||||
|
atomic_inc(&conf->mirrors[d].rdev->nr_pending);
|
||||||
|
bio->bi_next = biolist;
|
||||||
|
biolist = bio;
|
||||||
|
bio->bi_private = r10_bio;
|
||||||
|
bio->bi_end_io = end_sync_write;
|
||||||
|
bio->bi_rw = WRITE;
|
||||||
|
bio->bi_sector = sector +
|
||||||
|
conf->mirrors[d].replacement->data_offset;
|
||||||
|
bio->bi_bdev = conf->mirrors[d].replacement->bdev;
|
||||||
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count < 2) {
|
if (count < 2) {
|
||||||
|
@ -2757,6 +2843,11 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr,
|
||||||
if (r10_bio->devs[i].bio->bi_end_io)
|
if (r10_bio->devs[i].bio->bi_end_io)
|
||||||
rdev_dec_pending(conf->mirrors[d].rdev,
|
rdev_dec_pending(conf->mirrors[d].rdev,
|
||||||
mddev);
|
mddev);
|
||||||
|
if (r10_bio->devs[i].repl_bio &&
|
||||||
|
r10_bio->devs[i].repl_bio->bi_end_io)
|
||||||
|
rdev_dec_pending(
|
||||||
|
conf->mirrors[d].replacement,
|
||||||
|
mddev);
|
||||||
}
|
}
|
||||||
put_buf(r10_bio);
|
put_buf(r10_bio);
|
||||||
biolist = NULL;
|
biolist = NULL;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче