md/raid10: handle further errors during fix_read_error better.
If we find more read/write errors we should record a bad block before failing the device. Signed-off-by: NeilBrown <neilb@suse.de>
This commit is contained in:
parent
5e5702898e
commit
58c54fcca3
@ -1749,6 +1749,26 @@ static void check_decay_read_errors(mddev_t *mddev, mdk_rdev_t *rdev)
|
|||||||
atomic_set(&rdev->read_errors, read_errors >> hours_since_last);
|
atomic_set(&rdev->read_errors, read_errors >> hours_since_last);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int r10_sync_page_io(mdk_rdev_t *rdev, sector_t sector,
|
||||||
|
int sectors, struct page *page, int rw)
|
||||||
|
{
|
||||||
|
sector_t first_bad;
|
||||||
|
int bad_sectors;
|
||||||
|
|
||||||
|
if (is_badblock(rdev, sector, sectors, &first_bad, &bad_sectors)
|
||||||
|
&& (rw == READ || test_bit(WriteErrorSeen, &rdev->flags)))
|
||||||
|
return -1;
|
||||||
|
if (sync_page_io(rdev, sector, sectors << 9, page, rw, false))
|
||||||
|
/* success */
|
||||||
|
return 1;
|
||||||
|
if (rw == WRITE)
|
||||||
|
set_bit(WriteErrorSeen, &rdev->flags);
|
||||||
|
/* need to record an error - either for the block or the device */
|
||||||
|
if (!rdev_set_badblocks(rdev, sector, sectors, 0))
|
||||||
|
md_error(rdev->mddev, rdev);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is a kernel thread which:
|
* This is a kernel thread which:
|
||||||
*
|
*
|
||||||
@ -1832,9 +1852,19 @@ static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio)
|
|||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
/* Cannot read from anywhere -- bye bye array */
|
/* Cannot read from anywhere, just mark the block
|
||||||
|
* as bad on the first device to discourage future
|
||||||
|
* reads.
|
||||||
|
*/
|
||||||
int dn = r10_bio->devs[r10_bio->read_slot].devnum;
|
int dn = r10_bio->devs[r10_bio->read_slot].devnum;
|
||||||
md_error(mddev, conf->mirrors[dn].rdev);
|
rdev = conf->mirrors[dn].rdev;
|
||||||
|
|
||||||
|
if (!rdev_set_badblocks(
|
||||||
|
rdev,
|
||||||
|
r10_bio->devs[r10_bio->read_slot].addr
|
||||||
|
+ sect,
|
||||||
|
s, 0))
|
||||||
|
md_error(mddev, rdev);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1855,10 +1885,10 @@ static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio)
|
|||||||
|
|
||||||
atomic_inc(&rdev->nr_pending);
|
atomic_inc(&rdev->nr_pending);
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
if (sync_page_io(rdev,
|
if (r10_sync_page_io(rdev,
|
||||||
r10_bio->devs[sl].addr +
|
r10_bio->devs[sl].addr +
|
||||||
sect,
|
sect,
|
||||||
s<<9, conf->tmppage, WRITE, false)
|
s<<9, conf->tmppage, WRITE)
|
||||||
== 0) {
|
== 0) {
|
||||||
/* Well, this device is dead */
|
/* Well, this device is dead */
|
||||||
printk(KERN_NOTICE
|
printk(KERN_NOTICE
|
||||||
@ -1873,7 +1903,6 @@ static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio)
|
|||||||
"drive\n",
|
"drive\n",
|
||||||
mdname(mddev),
|
mdname(mddev),
|
||||||
bdevname(rdev->bdev, b));
|
bdevname(rdev->bdev, b));
|
||||||
md_error(mddev, rdev);
|
|
||||||
}
|
}
|
||||||
rdev_dec_pending(rdev, mddev);
|
rdev_dec_pending(rdev, mddev);
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
@ -1893,11 +1922,12 @@ static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio)
|
|||||||
|
|
||||||
atomic_inc(&rdev->nr_pending);
|
atomic_inc(&rdev->nr_pending);
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
if (sync_page_io(rdev,
|
switch (r10_sync_page_io(rdev,
|
||||||
r10_bio->devs[sl].addr +
|
r10_bio->devs[sl].addr +
|
||||||
sect,
|
sect,
|
||||||
s<<9, conf->tmppage,
|
s<<9, conf->tmppage,
|
||||||
READ, false) == 0) {
|
READ)) {
|
||||||
|
case 0:
|
||||||
/* Well, this device is dead */
|
/* Well, this device is dead */
|
||||||
printk(KERN_NOTICE
|
printk(KERN_NOTICE
|
||||||
"md/raid10:%s: unable to read back "
|
"md/raid10:%s: unable to read back "
|
||||||
@ -1911,9 +1941,8 @@ static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio)
|
|||||||
"drive\n",
|
"drive\n",
|
||||||
mdname(mddev),
|
mdname(mddev),
|
||||||
bdevname(rdev->bdev, b));
|
bdevname(rdev->bdev, b));
|
||||||
|
break;
|
||||||
md_error(mddev, rdev);
|
case 1:
|
||||||
} else {
|
|
||||||
printk(KERN_INFO
|
printk(KERN_INFO
|
||||||
"md/raid10:%s: read error corrected"
|
"md/raid10:%s: read error corrected"
|
||||||
" (%d sectors at %llu on %s)\n",
|
" (%d sectors at %llu on %s)\n",
|
||||||
|
Loading…
Reference in New Issue
Block a user