Skip to content

Commit 73d5c38

Browse files
committed
md: avoid races when stopping resync.
There has been a race in raid10 and raid1 for a long time which has only recently started showing up due to a scheduler changed. When a sync_read request finishes, as soon as reschedule_retry is called, another thread can mark the resync request as having completed, so md_do_sync can finish, ->stop can be called, and ->conf can be freed. So using conf after reschedule_retry is not safe. Similarly, when finishing a sync_write, calling md_done_sync must be the last thing we do, as it allows a chain of events which will free conf and other data structures. The first of these requires action in raid10.c The second requires action in raid1.c and raid10.c Cc: stable@kernel.org Signed-off-by: NeilBrown <neilb@suse.de>
1 parent 78200d4 commit 73d5c38

File tree

2 files changed

+6
-4
lines changed

2 files changed

+6
-4
lines changed

drivers/md/raid1.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1237,8 +1237,9 @@ static void end_sync_write(struct bio *bio, int error)
12371237
update_head_pos(mirror, r1_bio);
12381238

12391239
if (atomic_dec_and_test(&r1_bio->remaining)) {
1240-
md_done_sync(mddev, r1_bio->sectors, uptodate);
1240+
sector_t s = r1_bio->sectors;
12411241
put_buf(r1_bio);
1242+
md_done_sync(mddev, s, uptodate);
12421243
}
12431244
}
12441245

drivers/md/raid10.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1236,14 +1236,14 @@ static void end_sync_read(struct bio *bio, int error)
12361236
/* for reconstruct, we always reschedule after a read.
12371237
* for resync, only after all reads
12381238
*/
1239+
rdev_dec_pending(conf->mirrors[d].rdev, conf->mddev);
12391240
if (test_bit(R10BIO_IsRecover, &r10_bio->state) ||
12401241
atomic_dec_and_test(&r10_bio->remaining)) {
12411242
/* we have read all the blocks,
12421243
* do the comparison in process context in raid10d
12431244
*/
12441245
reschedule_retry(r10_bio);
12451246
}
1246-
rdev_dec_pending(conf->mirrors[d].rdev, conf->mddev);
12471247
}
12481248

12491249
static void end_sync_write(struct bio *bio, int error)
@@ -1264,19 +1264,20 @@ static void end_sync_write(struct bio *bio, int error)
12641264

12651265
update_head_pos(i, r10_bio);
12661266

1267+
rdev_dec_pending(conf->mirrors[d].rdev, mddev);
12671268
while (atomic_dec_and_test(&r10_bio->remaining)) {
12681269
if (r10_bio->master_bio == NULL) {
12691270
/* the primary of several recovery bios */
1270-
md_done_sync(mddev, r10_bio->sectors, 1);
1271+
sector_t s = r10_bio->sectors;
12711272
put_buf(r10_bio);
1273+
md_done_sync(mddev, s, 1);
12721274
break;
12731275
} else {
12741276
r10bio_t *r10_bio2 = (r10bio_t *)r10_bio->master_bio;
12751277
put_buf(r10_bio);
12761278
r10_bio = r10_bio2;
12771279
}
12781280
}
1279-
rdev_dec_pending(conf->mirrors[d].rdev, mddev);
12801281
}
12811282

12821283
/*

0 commit comments

Comments
 (0)