Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'md/3.11-fixes' of git://neil.brown.name/md

Pull md fixes from Neil Brown:
"Two more bugfixes for md in 3.11

Both marked for -stable, both since 3.3. I guess I should spend more
time testing..."

* tag 'md/3.11-fixes' of git://neil.brown.name/md:
md/raid5: fix interaction of 'replace' and 'recovery'.
md/raid10: remove use-after-free bug.

+18 -6
+7 -1
drivers/md/raid10.c
··· 2290 2290 d = r10_bio->devs[1].devnum; 2291 2291 wbio = r10_bio->devs[1].bio; 2292 2292 wbio2 = r10_bio->devs[1].repl_bio; 2293 + /* Need to test wbio2->bi_end_io before we call 2294 + * generic_make_request as if the former is NULL, 2295 + * the latter is free to free wbio2. 2296 + */ 2297 + if (wbio2 && !wbio2->bi_end_io) 2298 + wbio2 = NULL; 2293 2299 if (wbio->bi_end_io) { 2294 2300 atomic_inc(&conf->mirrors[d].rdev->nr_pending); 2295 2301 md_sync_acct(conf->mirrors[d].rdev->bdev, bio_sectors(wbio)); 2296 2302 generic_make_request(wbio); 2297 2303 } 2298 - if (wbio2 && wbio2->bi_end_io) { 2304 + if (wbio2) { 2299 2305 atomic_inc(&conf->mirrors[d].replacement->nr_pending); 2300 2306 md_sync_acct(conf->mirrors[d].replacement->bdev, 2301 2307 bio_sectors(wbio2));
+10 -5
drivers/md/raid5.c
··· 3462 3462 test_and_clear_bit(STRIPE_SYNC_REQUESTED, &sh->state)) { 3463 3463 set_bit(STRIPE_SYNCING, &sh->state); 3464 3464 clear_bit(STRIPE_INSYNC, &sh->state); 3465 + clear_bit(STRIPE_REPLACED, &sh->state); 3465 3466 } 3466 3467 spin_unlock(&sh->stripe_lock); 3467 3468 } ··· 3608 3607 handle_parity_checks5(conf, sh, &s, disks); 3609 3608 } 3610 3609 3611 - if (s.replacing && s.locked == 0 3612 - && !test_bit(STRIPE_INSYNC, &sh->state)) { 3610 + if ((s.replacing || s.syncing) && s.locked == 0 3611 + && !test_bit(STRIPE_COMPUTE_RUN, &sh->state) 3612 + && !test_bit(STRIPE_REPLACED, &sh->state)) { 3613 3613 /* Write out to replacement devices where possible */ 3614 3614 for (i = 0; i < conf->raid_disks; i++) 3615 - if (test_bit(R5_UPTODATE, &sh->dev[i].flags) && 3616 - test_bit(R5_NeedReplace, &sh->dev[i].flags)) { 3615 + if (test_bit(R5_NeedReplace, &sh->dev[i].flags)) { 3616 + WARN_ON(!test_bit(R5_UPTODATE, &sh->dev[i].flags)); 3617 3617 set_bit(R5_WantReplace, &sh->dev[i].flags); 3618 3618 set_bit(R5_LOCKED, &sh->dev[i].flags); 3619 3619 s.locked++; 3620 3620 } 3621 - set_bit(STRIPE_INSYNC, &sh->state); 3621 + if (s.replacing) 3622 + set_bit(STRIPE_INSYNC, &sh->state); 3623 + set_bit(STRIPE_REPLACED, &sh->state); 3622 3624 } 3623 3625 if ((s.syncing || s.replacing) && s.locked == 0 && 3626 + !test_bit(STRIPE_COMPUTE_RUN, &sh->state) && 3624 3627 test_bit(STRIPE_INSYNC, &sh->state)) { 3625 3628 md_done_sync(conf->mddev, STRIPE_SECTORS, 1); 3626 3629 clear_bit(STRIPE_SYNCING, &sh->state);
+1
drivers/md/raid5.h
··· 306 306 STRIPE_SYNC_REQUESTED, 307 307 STRIPE_SYNCING, 308 308 STRIPE_INSYNC, 309 + STRIPE_REPLACED, 309 310 STRIPE_PREREAD_ACTIVE, 310 311 STRIPE_DELAYED, 311 312 STRIPE_DEGRADED,