Skip to content

Commit 6c286e8

Browse files
committed
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
2 parents e12d8d5 + 1217e1d commit 6c286e8

File tree

4 files changed

+30
-19
lines changed

4 files changed

+30
-19
lines changed

drivers/md/md.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3887,10 +3887,10 @@ array_state_show(struct mddev *mddev, char *page)
38873887
st = read_auto;
38883888
break;
38893889
case 0:
3890-
if (mddev->in_sync)
3891-
st = clean;
3892-
else if (test_bit(MD_CHANGE_PENDING, &mddev->flags))
3890+
if (test_bit(MD_CHANGE_PENDING, &mddev->flags))
38933891
st = write_pending;
3892+
else if (mddev->in_sync)
3893+
st = clean;
38943894
else if (mddev->safemode)
38953895
st = active_idle;
38963896
else
@@ -8144,14 +8144,14 @@ void md_do_sync(struct md_thread *thread)
81448144

81458145
if (!test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) &&
81468146
!test_bit(MD_RECOVERY_INTR, &mddev->recovery) &&
8147-
mddev->curr_resync > 2) {
8147+
mddev->curr_resync > 3) {
81488148
mddev->curr_resync_completed = mddev->curr_resync;
81498149
sysfs_notify(&mddev->kobj, NULL, "sync_completed");
81508150
}
81518151
mddev->pers->sync_request(mddev, max_sectors, &skipped);
81528152

81538153
if (!test_bit(MD_RECOVERY_CHECK, &mddev->recovery) &&
8154-
mddev->curr_resync > 2) {
8154+
mddev->curr_resync > 3) {
81558155
if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) {
81568156
if (test_bit(MD_RECOVERY_INTR, &mddev->recovery)) {
81578157
if (mddev->curr_resync >= mddev->recovery_cp) {

drivers/md/raid1.c

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -403,11 +403,14 @@ static void raid1_end_write_request(struct bio *bio)
403403
struct bio *to_put = NULL;
404404
int mirror = find_bio_disk(r1_bio, bio);
405405
struct md_rdev *rdev = conf->mirrors[mirror].rdev;
406+
bool discard_error;
407+
408+
discard_error = bio->bi_error && bio_op(bio) == REQ_OP_DISCARD;
406409

407410
/*
408411
* 'one mirror IO has finished' event handler:
409412
*/
410-
if (bio->bi_error) {
413+
if (bio->bi_error && !discard_error) {
411414
set_bit(WriteErrorSeen, &rdev->flags);
412415
if (!test_and_set_bit(WantReplacement, &rdev->flags))
413416
set_bit(MD_RECOVERY_NEEDED, &
@@ -444,7 +447,7 @@ static void raid1_end_write_request(struct bio *bio)
444447

445448
/* Maybe we can clear some bad blocks. */
446449
if (is_badblock(rdev, r1_bio->sector, r1_bio->sectors,
447-
&first_bad, &bad_sectors)) {
450+
&first_bad, &bad_sectors) && !discard_error) {
448451
r1_bio->bios[mirror] = IO_MADE_GOOD;
449452
set_bit(R1BIO_MadeGood, &r1_bio->state);
450453
}
@@ -2294,17 +2297,23 @@ static void handle_read_error(struct r1conf *conf, struct r1bio *r1_bio)
22942297
* This is all done synchronously while the array is
22952298
* frozen
22962299
*/
2300+
2301+
bio = r1_bio->bios[r1_bio->read_disk];
2302+
bdevname(bio->bi_bdev, b);
2303+
bio_put(bio);
2304+
r1_bio->bios[r1_bio->read_disk] = NULL;
2305+
22972306
if (mddev->ro == 0) {
22982307
freeze_array(conf, 1);
22992308
fix_read_error(conf, r1_bio->read_disk,
23002309
r1_bio->sector, r1_bio->sectors);
23012310
unfreeze_array(conf);
2302-
} else
2303-
md_error(mddev, conf->mirrors[r1_bio->read_disk].rdev);
2311+
} else {
2312+
r1_bio->bios[r1_bio->read_disk] = IO_BLOCKED;
2313+
}
2314+
23042315
rdev_dec_pending(conf->mirrors[r1_bio->read_disk].rdev, conf->mddev);
23052316

2306-
bio = r1_bio->bios[r1_bio->read_disk];
2307-
bdevname(bio->bi_bdev, b);
23082317
read_more:
23092318
disk = read_balance(conf, r1_bio, &max_sectors);
23102319
if (disk == -1) {
@@ -2315,11 +2324,6 @@ static void handle_read_error(struct r1conf *conf, struct r1bio *r1_bio)
23152324
} else {
23162325
const unsigned long do_sync
23172326
= r1_bio->master_bio->bi_opf & REQ_SYNC;
2318-
if (bio) {
2319-
r1_bio->bios[r1_bio->read_disk] =
2320-
mddev->ro ? IO_BLOCKED : NULL;
2321-
bio_put(bio);
2322-
}
23232327
r1_bio->read_disk = disk;
23242328
bio = bio_clone_mddev(r1_bio->master_bio, GFP_NOIO, mddev);
23252329
bio_trim(bio, r1_bio->sector - bio->bi_iter.bi_sector,

drivers/md/raid10.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,9 @@ static void raid10_end_write_request(struct bio *bio)
447447
struct r10conf *conf = r10_bio->mddev->private;
448448
int slot, repl;
449449
struct md_rdev *rdev = NULL;
450+
bool discard_error;
451+
452+
discard_error = bio->bi_error && bio_op(bio) == REQ_OP_DISCARD;
450453

451454
dev = find_bio_disk(conf, r10_bio, bio, &slot, &repl);
452455

@@ -460,7 +463,7 @@ static void raid10_end_write_request(struct bio *bio)
460463
/*
461464
* this branch is our 'one mirror IO has finished' event handler:
462465
*/
463-
if (bio->bi_error) {
466+
if (bio->bi_error && !discard_error) {
464467
if (repl)
465468
/* Never record new bad blocks to replacement,
466469
* just fail it.
@@ -503,7 +506,7 @@ static void raid10_end_write_request(struct bio *bio)
503506
if (is_badblock(rdev,
504507
r10_bio->devs[slot].addr,
505508
r10_bio->sectors,
506-
&first_bad, &bad_sectors)) {
509+
&first_bad, &bad_sectors) && !discard_error) {
507510
bio_put(bio);
508511
if (repl)
509512
r10_bio->devs[slot].repl_bio = IO_MADE_GOOD;

drivers/md/raid5-cache.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1087,7 +1087,7 @@ static int r5l_recovery_log(struct r5l_log *log)
10871087
* 1's seq + 10 and let superblock points to meta2. The same recovery will
10881088
* not think meta 3 is a valid meta, because its seq doesn't match
10891089
*/
1090-
if (ctx.seq > log->last_cp_seq + 1) {
1090+
if (ctx.seq > log->last_cp_seq) {
10911091
int ret;
10921092

10931093
ret = r5l_log_write_empty_meta_block(log, ctx.pos, ctx.seq + 10);
@@ -1096,6 +1096,8 @@ static int r5l_recovery_log(struct r5l_log *log)
10961096
log->seq = ctx.seq + 11;
10971097
log->log_start = r5l_ring_add(log, ctx.pos, BLOCK_SECTORS);
10981098
r5l_write_super(log, ctx.pos);
1099+
log->last_checkpoint = ctx.pos;
1100+
log->next_checkpoint = ctx.pos;
10991101
} else {
11001102
log->log_start = ctx.pos;
11011103
log->seq = ctx.seq;
@@ -1154,6 +1156,7 @@ static int r5l_load_log(struct r5l_log *log)
11541156
if (create_super) {
11551157
log->last_cp_seq = prandom_u32();
11561158
cp = 0;
1159+
r5l_log_write_empty_meta_block(log, cp, log->last_cp_seq);
11571160
/*
11581161
* Make sure super points to correct address. Log might have
11591162
* data very soon. If super hasn't correct log tail address,
@@ -1168,6 +1171,7 @@ static int r5l_load_log(struct r5l_log *log)
11681171
if (log->max_free_space > RECLAIM_MAX_FREE_SPACE)
11691172
log->max_free_space = RECLAIM_MAX_FREE_SPACE;
11701173
log->last_checkpoint = cp;
1174+
log->next_checkpoint = cp;
11711175

11721176
__free_page(page);
11731177

0 commit comments

Comments
 (0)