Skip to content
This repository has been archived by the owner on Aug 27, 2022. It is now read-only.

Commit

Permalink
md/raid10: avoid reading known bad blocks during resync/recovery.
Browse files Browse the repository at this point in the history
During resync/recovery limit the size of the request to avoid
reading into a bad block that does not start at-or-before the current
read address.

Similarly if there is a bad block at this address, don't allow the
current request to extend beyond the end of that bad block.

Now that we don't ever read from known bad blocks, it is safe to allow
devices with those blocks into the array.

Signed-off-by: NeilBrown <neilb@suse.de>
  • Loading branch information
neilbrown committed Jul 28, 2011
1 parent 8dbed5c commit 40c356c
Showing 1 changed file with 35 additions and 9 deletions.
44 changes: 35 additions & 9 deletions drivers/md/raid10.c
Original file line number Diff line number Diff line change
Expand Up @@ -1203,9 +1203,6 @@ static int raid10_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
int first = 0;
int last = conf->raid_disks - 1;

if (rdev->badblocks.count)
return -EINVAL;

if (mddev->recovery_cp < MaxSector)
/* only hot-add to in-sync arrays, as recovery is
* very different from resync
Expand Down Expand Up @@ -1927,7 +1924,6 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr,
int i;
int max_sync;
sector_t sync_blocks;

sector_t sectors_skipped = 0;
int chunks_skipped = 0;

Expand Down Expand Up @@ -2070,10 +2066,28 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr,

for (j=0; j<conf->copies;j++) {
int d = r10_bio->devs[j].devnum;
mdk_rdev_t *rdev;
sector_t sector, first_bad;
int bad_sectors;
if (!conf->mirrors[d].rdev ||
!test_bit(In_sync, &conf->mirrors[d].rdev->flags))
continue;
/* This is where we read from */
rdev = conf->mirrors[d].rdev;
sector = r10_bio->devs[j].addr;

if (is_badblock(rdev, sector, max_sync,
&first_bad, &bad_sectors)) {
if (first_bad > sector)
max_sync = first_bad - sector;
else {
bad_sectors -= (sector
- first_bad);
if (max_sync > bad_sectors)
max_sync = bad_sectors;
continue;
}
}
bio = r10_bio->devs[0].bio;
bio->bi_next = biolist;
biolist = bio;
Expand Down Expand Up @@ -2160,20 +2174,36 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr,

for (i=0; i<conf->copies; i++) {
int d = r10_bio->devs[i].devnum;
sector_t first_bad, sector;
int bad_sectors;

bio = r10_bio->devs[i].bio;
bio->bi_end_io = NULL;
clear_bit(BIO_UPTODATE, &bio->bi_flags);
if (conf->mirrors[d].rdev == NULL ||
test_bit(Faulty, &conf->mirrors[d].rdev->flags))
continue;
sector = r10_bio->devs[i].addr;
if (is_badblock(conf->mirrors[d].rdev,
sector, max_sync,
&first_bad, &bad_sectors)) {
if (first_bad > sector)
max_sync = first_bad - sector;
else {
bad_sectors -= (sector - first_bad);
if (max_sync > bad_sectors)
max_sync = max_sync;
continue;
}
}
atomic_inc(&conf->mirrors[d].rdev->nr_pending);
atomic_inc(&r10_bio->remaining);
bio->bi_next = biolist;
biolist = bio;
bio->bi_private = r10_bio;
bio->bi_end_io = end_sync_read;
bio->bi_rw = READ;
bio->bi_sector = r10_bio->devs[i].addr +
bio->bi_sector = sector +
conf->mirrors[d].rdev->data_offset;
bio->bi_bdev = conf->mirrors[d].rdev->bdev;
count++;
Expand Down Expand Up @@ -2431,10 +2461,6 @@ static int run(mddev_t *mddev)

list_for_each_entry(rdev, &mddev->disks, same_set) {

if (rdev->badblocks.count) {
printk(KERN_ERR "md/raid10: cannot handle bad blocks yet\n");
goto out_free_conf;
}
disk_idx = rdev->raid_disk;
if (disk_idx >= conf->raid_disks
|| disk_idx < 0)
Expand Down

0 comments on commit 40c356c

Please sign in to comment.