diff options
Diffstat (limited to 'drivers/md')
-rw-r--r-- | drivers/md/raid1.c | 29 | ||||
-rw-r--r-- | drivers/md/raid10.c | 46 |
2 files changed, 48 insertions, 27 deletions
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 6081941de1b3..4070eff6f0f8 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c | |||
@@ -315,10 +315,11 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int | |||
315 | if (r1_bio->bios[mirror] == bio) | 315 | if (r1_bio->bios[mirror] == bio) |
316 | break; | 316 | break; |
317 | 317 | ||
318 | if (error == -ENOTSUPP && test_bit(R1BIO_Barrier, &r1_bio->state)) { | 318 | if (error == -EOPNOTSUPP && test_bit(R1BIO_Barrier, &r1_bio->state)) { |
319 | set_bit(BarriersNotsupp, &conf->mirrors[mirror].rdev->flags); | 319 | set_bit(BarriersNotsupp, &conf->mirrors[mirror].rdev->flags); |
320 | set_bit(R1BIO_BarrierRetry, &r1_bio->state); | 320 | set_bit(R1BIO_BarrierRetry, &r1_bio->state); |
321 | r1_bio->mddev->barriers_work = 0; | 321 | r1_bio->mddev->barriers_work = 0; |
322 | /* Don't rdev_dec_pending in this branch - keep it for the retry */ | ||
322 | } else { | 323 | } else { |
323 | /* | 324 | /* |
324 | * this branch is our 'one mirror IO has finished' event handler: | 325 | * this branch is our 'one mirror IO has finished' event handler: |
@@ -365,6 +366,7 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int | |||
365 | } | 366 | } |
366 | } | 367 | } |
367 | } | 368 | } |
369 | rdev_dec_pending(conf->mirrors[mirror].rdev, conf->mddev); | ||
368 | } | 370 | } |
369 | /* | 371 | /* |
370 | * | 372 | * |
@@ -374,11 +376,9 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int | |||
374 | if (atomic_dec_and_test(&r1_bio->remaining)) { | 376 | if (atomic_dec_and_test(&r1_bio->remaining)) { |
375 | if (test_bit(R1BIO_BarrierRetry, &r1_bio->state)) { | 377 | if (test_bit(R1BIO_BarrierRetry, &r1_bio->state)) { |
376 | reschedule_retry(r1_bio); | 378 | reschedule_retry(r1_bio); |
377 | /* Don't dec_pending yet, we want to hold | ||
378 | * the reference over the retry | ||
379 | */ | ||
380 | goto out; | 379 | goto out; |
381 | } | 380 | } |
381 | /* it really is the end of this request */ | ||
382 | if (test_bit(R1BIO_BehindIO, &r1_bio->state)) { | 382 | if (test_bit(R1BIO_BehindIO, &r1_bio->state)) { |
383 | /* free extra copy of the data pages */ | 383 | /* free extra copy of the data pages */ |
384 | int i = bio->bi_vcnt; | 384 | int i = bio->bi_vcnt; |
@@ -393,8 +393,6 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int | |||
393 | md_write_end(r1_bio->mddev); | 393 | md_write_end(r1_bio->mddev); |
394 | raid_end_bio_io(r1_bio); | 394 | raid_end_bio_io(r1_bio); |
395 | } | 395 | } |
396 | |||
397 | rdev_dec_pending(conf->mirrors[mirror].rdev, conf->mddev); | ||
398 | out: | 396 | out: |
399 | if (to_put) | 397 | if (to_put) |
400 | bio_put(to_put); | 398 | bio_put(to_put); |
@@ -753,18 +751,24 @@ static int make_request(request_queue_t *q, struct bio * bio) | |||
753 | const int rw = bio_data_dir(bio); | 751 | const int rw = bio_data_dir(bio); |
754 | int do_barriers; | 752 | int do_barriers; |
755 | 753 | ||
756 | if (unlikely(!mddev->barriers_work && bio_barrier(bio))) { | ||
757 | bio_endio(bio, bio->bi_size, -EOPNOTSUPP); | ||
758 | return 0; | ||
759 | } | ||
760 | |||
761 | /* | 754 | /* |
762 | * Register the new request and wait if the reconstruction | 755 | * Register the new request and wait if the reconstruction |
763 | * thread has put up a bar for new requests. | 756 | * thread has put up a bar for new requests. |
764 | * Continue immediately if no resync is active currently. | 757 | * Continue immediately if no resync is active currently. |
758 | * We test barriers_work *after* md_write_start as md_write_start | ||
759 | * may cause the first superblock write, and that will check out | ||
760 | * if barriers work. | ||
765 | */ | 761 | */ |
762 | |||
766 | md_write_start(mddev, bio); /* wait on superblock update early */ | 763 | md_write_start(mddev, bio); /* wait on superblock update early */ |
767 | 764 | ||
765 | if (unlikely(!mddev->barriers_work && bio_barrier(bio))) { | ||
766 | if (rw == WRITE) | ||
767 | md_write_end(mddev); | ||
768 | bio_endio(bio, bio->bi_size, -EOPNOTSUPP); | ||
769 | return 0; | ||
770 | } | ||
771 | |||
768 | wait_barrier(conf); | 772 | wait_barrier(conf); |
769 | 773 | ||
770 | disk_stat_inc(mddev->gendisk, ios[rw]); | 774 | disk_stat_inc(mddev->gendisk, ios[rw]); |
@@ -1404,10 +1408,11 @@ static void raid1d(mddev_t *mddev) | |||
1404 | unplug = 1; | 1408 | unplug = 1; |
1405 | } else if (test_bit(R1BIO_BarrierRetry, &r1_bio->state)) { | 1409 | } else if (test_bit(R1BIO_BarrierRetry, &r1_bio->state)) { |
1406 | /* some requests in the r1bio were BIO_RW_BARRIER | 1410 | /* some requests in the r1bio were BIO_RW_BARRIER |
1407 | * requests which failed with -ENOTSUPP. Hohumm.. | 1411 | * requests which failed with -EOPNOTSUPP. Hohumm.. |
1408 | * Better resubmit without the barrier. | 1412 | * Better resubmit without the barrier. |
1409 | * We know which devices to resubmit for, because | 1413 | * We know which devices to resubmit for, because |
1410 | * all others have had their bios[] entry cleared. | 1414 | * all others have had their bios[] entry cleared. |
1415 | * We already have a nr_pending reference on these rdevs. | ||
1411 | */ | 1416 | */ |
1412 | int i; | 1417 | int i; |
1413 | clear_bit(R1BIO_BarrierRetry, &r1_bio->state); | 1418 | clear_bit(R1BIO_BarrierRetry, &r1_bio->state); |
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 617012bc107a..1440935414e6 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c | |||
@@ -1407,43 +1407,54 @@ static void raid10d(mddev_t *mddev) | |||
1407 | if (s > (PAGE_SIZE>>9)) | 1407 | if (s > (PAGE_SIZE>>9)) |
1408 | s = PAGE_SIZE >> 9; | 1408 | s = PAGE_SIZE >> 9; |
1409 | 1409 | ||
1410 | rcu_read_lock(); | ||
1410 | do { | 1411 | do { |
1411 | int d = r10_bio->devs[sl].devnum; | 1412 | int d = r10_bio->devs[sl].devnum; |
1412 | rdev = conf->mirrors[d].rdev; | 1413 | rdev = rcu_dereference(conf->mirrors[d].rdev); |
1413 | if (rdev && | 1414 | if (rdev && |
1414 | test_bit(In_sync, &rdev->flags) && | 1415 | test_bit(In_sync, &rdev->flags)) { |
1415 | sync_page_io(rdev->bdev, | 1416 | atomic_inc(&rdev->nr_pending); |
1416 | r10_bio->devs[sl].addr + | 1417 | rcu_read_unlock(); |
1417 | sect + rdev->data_offset, | 1418 | success = sync_page_io(rdev->bdev, |
1418 | s<<9, | 1419 | r10_bio->devs[sl].addr + |
1419 | conf->tmppage, READ)) | 1420 | sect + rdev->data_offset, |
1420 | success = 1; | 1421 | s<<9, |
1421 | else { | 1422 | conf->tmppage, READ); |
1422 | sl++; | 1423 | rdev_dec_pending(rdev, mddev); |
1423 | if (sl == conf->copies) | 1424 | rcu_read_lock(); |
1424 | sl = 0; | 1425 | if (success) |
1426 | break; | ||
1425 | } | 1427 | } |
1428 | sl++; | ||
1429 | if (sl == conf->copies) | ||
1430 | sl = 0; | ||
1426 | } while (!success && sl != r10_bio->read_slot); | 1431 | } while (!success && sl != r10_bio->read_slot); |
1432 | rcu_read_unlock(); | ||
1427 | 1433 | ||
1428 | if (success) { | 1434 | if (success) { |
1429 | int start = sl; | 1435 | int start = sl; |
1430 | /* write it back and re-read */ | 1436 | /* write it back and re-read */ |
1437 | rcu_read_lock(); | ||
1431 | while (sl != r10_bio->read_slot) { | 1438 | while (sl != r10_bio->read_slot) { |
1432 | int d; | 1439 | int d; |
1433 | if (sl==0) | 1440 | if (sl==0) |
1434 | sl = conf->copies; | 1441 | sl = conf->copies; |
1435 | sl--; | 1442 | sl--; |
1436 | d = r10_bio->devs[sl].devnum; | 1443 | d = r10_bio->devs[sl].devnum; |
1437 | rdev = conf->mirrors[d].rdev; | 1444 | rdev = rcu_dereference(conf->mirrors[d].rdev); |
1438 | atomic_add(s, &rdev->corrected_errors); | ||
1439 | if (rdev && | 1445 | if (rdev && |
1440 | test_bit(In_sync, &rdev->flags)) { | 1446 | test_bit(In_sync, &rdev->flags)) { |
1447 | atomic_inc(&rdev->nr_pending); | ||
1448 | rcu_read_unlock(); | ||
1449 | atomic_add(s, &rdev->corrected_errors); | ||
1441 | if (sync_page_io(rdev->bdev, | 1450 | if (sync_page_io(rdev->bdev, |
1442 | r10_bio->devs[sl].addr + | 1451 | r10_bio->devs[sl].addr + |
1443 | sect + rdev->data_offset, | 1452 | sect + rdev->data_offset, |
1444 | s<<9, conf->tmppage, WRITE) == 0) | 1453 | s<<9, conf->tmppage, WRITE) == 0) |
1445 | /* Well, this device is dead */ | 1454 | /* Well, this device is dead */ |
1446 | md_error(mddev, rdev); | 1455 | md_error(mddev, rdev); |
1456 | rdev_dec_pending(rdev, mddev); | ||
1457 | rcu_read_lock(); | ||
1447 | } | 1458 | } |
1448 | } | 1459 | } |
1449 | sl = start; | 1460 | sl = start; |
@@ -1453,17 +1464,22 @@ static void raid10d(mddev_t *mddev) | |||
1453 | sl = conf->copies; | 1464 | sl = conf->copies; |
1454 | sl--; | 1465 | sl--; |
1455 | d = r10_bio->devs[sl].devnum; | 1466 | d = r10_bio->devs[sl].devnum; |
1456 | rdev = conf->mirrors[d].rdev; | 1467 | rdev = rcu_dereference(conf->mirrors[d].rdev); |
1457 | if (rdev && | 1468 | if (rdev && |
1458 | test_bit(In_sync, &rdev->flags)) { | 1469 | test_bit(In_sync, &rdev->flags)) { |
1470 | atomic_inc(&rdev->nr_pending); | ||
1471 | rcu_read_unlock(); | ||
1459 | if (sync_page_io(rdev->bdev, | 1472 | if (sync_page_io(rdev->bdev, |
1460 | r10_bio->devs[sl].addr + | 1473 | r10_bio->devs[sl].addr + |
1461 | sect + rdev->data_offset, | 1474 | sect + rdev->data_offset, |
1462 | s<<9, conf->tmppage, READ) == 0) | 1475 | s<<9, conf->tmppage, READ) == 0) |
1463 | /* Well, this device is dead */ | 1476 | /* Well, this device is dead */ |
1464 | md_error(mddev, rdev); | 1477 | md_error(mddev, rdev); |
1478 | rdev_dec_pending(rdev, mddev); | ||
1479 | rcu_read_lock(); | ||
1465 | } | 1480 | } |
1466 | } | 1481 | } |
1482 | rcu_read_unlock(); | ||
1467 | } else { | 1483 | } else { |
1468 | /* Cannot read from anywhere -- bye bye array */ | 1484 | /* Cannot read from anywhere -- bye bye array */ |
1469 | md_error(mddev, conf->mirrors[r10_bio->devs[r10_bio->read_slot].devnum].rdev); | 1485 | md_error(mddev, conf->mirrors[r10_bio->devs[r10_bio->read_slot].devnum].rdev); |