diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-11-05 11:34:07 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-11-05 11:34:07 -0700 |
commit | 6c286e812d5f306ebf991c3f78ebc511121896e0 (patch) | |
tree | db4345eba03a3245d2377e60d92275d1776e4e7a /drivers/md/raid1.c | |
parent | e12d8d512f090b6c540c7f75bf879f0d6a908587 (diff) | |
parent | 1217e1d1999ed6c9c1e1b1acae0a74ab70464ae2 (diff) |
Merge tag 'md/4.9-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/shli/md
Pull MD fixes from Shaohua Li:
"There are several bug fixes queued:
- fix raid5-cache recovery bugs
- fix discard IO error handling for raid1/10
- fix array sync writes bogus position to superblock
- fix IO error handling for raid array with external metadata"
* tag 'md/4.9-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/shli/md:
md: be careful not lot leak internal curr_resync value into metadata. -- (all)
raid1: handle read error also in readonly mode
raid5-cache: correct condition for empty metadata write
md: report 'write_pending' state when array in sync
md/raid5: write an empty meta-block when creating log super-block
md/raid5: initialize next_checkpoint field before use
RAID10: ignore discard error
RAID1: ignore discard error
Diffstat (limited to 'drivers/md/raid1.c')
-rw-r--r-- | drivers/md/raid1.c | 26 |
1 files changed, 15 insertions, 11 deletions
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 1961d827dbd1..29e2df5cd77b 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -403,11 +403,14 @@ static void raid1_end_write_request(struct bio *bio) struct bio *to_put = NULL; int mirror = find_bio_disk(r1_bio, bio); struct md_rdev *rdev = conf->mirrors[mirror].rdev; + bool discard_error; + + discard_error = bio->bi_error && bio_op(bio) == REQ_OP_DISCARD; /* * 'one mirror IO has finished' event handler: */ - if (bio->bi_error) { + if (bio->bi_error && !discard_error) { set_bit(WriteErrorSeen, &rdev->flags); if (!test_and_set_bit(WantReplacement, &rdev->flags)) set_bit(MD_RECOVERY_NEEDED, & @@ -444,7 +447,7 @@ static void raid1_end_write_request(struct bio *bio) /* Maybe we can clear some bad blocks. */ if (is_badblock(rdev, r1_bio->sector, r1_bio->sectors, - &first_bad, &bad_sectors)) { + &first_bad, &bad_sectors) && !discard_error) { r1_bio->bios[mirror] = IO_MADE_GOOD; set_bit(R1BIO_MadeGood, &r1_bio->state); } @@ -2294,17 +2297,23 @@ static void handle_read_error(struct r1conf *conf, struct r1bio *r1_bio) * This is all done synchronously while the array is * frozen */ + + bio = r1_bio->bios[r1_bio->read_disk]; + bdevname(bio->bi_bdev, b); + bio_put(bio); + r1_bio->bios[r1_bio->read_disk] = NULL; + if (mddev->ro == 0) { freeze_array(conf, 1); fix_read_error(conf, r1_bio->read_disk, r1_bio->sector, r1_bio->sectors); unfreeze_array(conf); - } else - md_error(mddev, conf->mirrors[r1_bio->read_disk].rdev); + } else { + r1_bio->bios[r1_bio->read_disk] = IO_BLOCKED; + } + rdev_dec_pending(conf->mirrors[r1_bio->read_disk].rdev, conf->mddev); - bio = r1_bio->bios[r1_bio->read_disk]; - bdevname(bio->bi_bdev, b); read_more: disk = read_balance(conf, r1_bio, &max_sectors); if (disk == -1) { @@ -2315,11 +2324,6 @@ read_more: } else { const unsigned long do_sync = r1_bio->master_bio->bi_opf & REQ_SYNC; - if (bio) { - r1_bio->bios[r1_bio->read_disk] = - mddev->ro ? IO_BLOCKED : NULL; - bio_put(bio); - } r1_bio->read_disk = disk; bio = bio_clone_mddev(r1_bio->master_bio, GFP_NOIO, mddev); bio_trim(bio, r1_bio->sector - bio->bi_iter.bi_sector, |