diff options
author | NeilBrown <neilb@suse.de> | 2011-05-11 00:27:03 -0400 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2011-05-11 00:27:03 -0400 |
commit | 56d9912106b0974ffb6dd264c80c7e816677e998 (patch) | |
tree | eef9208cffd7bc4501ca57250a4b884a04aa116b /drivers/md | |
parent | 8258c53208d7a9b7207e7d4dae36d2ea384cb278 (diff) |
md: simplify raid10 read_balance
raid10 read balance has two different loop for looking through
possible devices to chose the best.
Collapse those into one loop and generally make the code more
readable.
Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'drivers/md')
-rw-r--r-- | drivers/md/raid10.c | 110 |
1 files changed, 44 insertions, 66 deletions
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 8e9462626ec5..8ea0acad606b 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c | |||
@@ -488,13 +488,19 @@ static int raid10_mergeable_bvec(struct request_queue *q, | |||
488 | static int read_balance(conf_t *conf, r10bio_t *r10_bio) | 488 | static int read_balance(conf_t *conf, r10bio_t *r10_bio) |
489 | { | 489 | { |
490 | const sector_t this_sector = r10_bio->sector; | 490 | const sector_t this_sector = r10_bio->sector; |
491 | int disk, slot, nslot; | 491 | int disk, slot; |
492 | const int sectors = r10_bio->sectors; | 492 | const int sectors = r10_bio->sectors; |
493 | sector_t new_distance, current_distance; | 493 | sector_t new_distance, best_dist; |
494 | mdk_rdev_t *rdev; | 494 | mdk_rdev_t *rdev; |
495 | int do_balance; | ||
496 | int best_slot; | ||
495 | 497 | ||
496 | raid10_find_phys(conf, r10_bio); | 498 | raid10_find_phys(conf, r10_bio); |
497 | rcu_read_lock(); | 499 | rcu_read_lock(); |
500 | retry: | ||
501 | best_slot = -1; | ||
502 | best_dist = MaxSector; | ||
503 | do_balance = 1; | ||
498 | /* | 504 | /* |
499 | * Check if we can balance. We can balance on the whole | 505 | * Check if we can balance. We can balance on the whole |
500 | * device if no resync is going on (recovery is ok), or below | 506 | * device if no resync is going on (recovery is ok), or below |
@@ -502,86 +508,58 @@ static int read_balance(conf_t *conf, r10bio_t *r10_bio) | |||
502 | * above the resync window. | 508 | * above the resync window. |
503 | */ | 509 | */ |
504 | if (conf->mddev->recovery_cp < MaxSector | 510 | if (conf->mddev->recovery_cp < MaxSector |
505 | && (this_sector + sectors >= conf->next_resync)) { | 511 | && (this_sector + sectors >= conf->next_resync)) |
506 | /* make sure that disk is operational */ | 512 | do_balance = 0; |
507 | slot = 0; | ||
508 | disk = r10_bio->devs[slot].devnum; | ||
509 | |||
510 | while ((rdev = rcu_dereference(conf->mirrors[disk].rdev)) == NULL || | ||
511 | r10_bio->devs[slot].bio == IO_BLOCKED || | ||
512 | !test_bit(In_sync, &rdev->flags)) { | ||
513 | slot++; | ||
514 | if (slot == conf->copies) { | ||
515 | slot = 0; | ||
516 | disk = -1; | ||
517 | break; | ||
518 | } | ||
519 | disk = r10_bio->devs[slot].devnum; | ||
520 | } | ||
521 | goto rb_out; | ||
522 | } | ||
523 | |||
524 | 513 | ||
525 | /* make sure the disk is operational */ | 514 | for (slot = 0; slot < conf->copies ; slot++) { |
526 | slot = 0; | 515 | if (r10_bio->devs[slot].bio == IO_BLOCKED) |
527 | disk = r10_bio->devs[slot].devnum; | 516 | continue; |
528 | while ((rdev=rcu_dereference(conf->mirrors[disk].rdev)) == NULL || | ||
529 | r10_bio->devs[slot].bio == IO_BLOCKED || | ||
530 | !test_bit(In_sync, &rdev->flags)) { | ||
531 | slot ++; | ||
532 | if (slot == conf->copies) { | ||
533 | disk = -1; | ||
534 | goto rb_out; | ||
535 | } | ||
536 | disk = r10_bio->devs[slot].devnum; | 517 | disk = r10_bio->devs[slot].devnum; |
537 | } | 518 | rdev = rcu_dereference(conf->mirrors[disk].rdev); |
538 | 519 | if (rdev == NULL) | |
539 | 520 | continue; | |
540 | current_distance = abs(r10_bio->devs[slot].addr - | 521 | if (!test_bit(In_sync, &rdev->flags)) |
541 | conf->mirrors[disk].head_position); | ||
542 | |||
543 | /* Find the disk whose head is closest, | ||
544 | * or - for far > 1 - find the closest to partition beginning */ | ||
545 | |||
546 | for (nslot = slot; nslot < conf->copies; nslot++) { | ||
547 | int ndisk = r10_bio->devs[nslot].devnum; | ||
548 | |||
549 | |||
550 | if ((rdev=rcu_dereference(conf->mirrors[ndisk].rdev)) == NULL || | ||
551 | r10_bio->devs[nslot].bio == IO_BLOCKED || | ||
552 | !test_bit(In_sync, &rdev->flags)) | ||
553 | continue; | 522 | continue; |
554 | 523 | ||
524 | if (!do_balance) | ||
525 | break; | ||
526 | |||
555 | /* This optimisation is debatable, and completely destroys | 527 | /* This optimisation is debatable, and completely destroys |
556 | * sequential read speed for 'far copies' arrays. So only | 528 | * sequential read speed for 'far copies' arrays. So only |
557 | * keep it for 'near' arrays, and review those later. | 529 | * keep it for 'near' arrays, and review those later. |
558 | */ | 530 | */ |
559 | if (conf->near_copies > 1 && !atomic_read(&rdev->nr_pending)) { | 531 | if (conf->near_copies > 1 && !atomic_read(&rdev->nr_pending)) |
560 | disk = ndisk; | ||
561 | slot = nslot; | ||
562 | break; | 532 | break; |
563 | } | ||
564 | 533 | ||
565 | /* for far > 1 always use the lowest address */ | 534 | /* for far > 1 always use the lowest address */ |
566 | if (conf->far_copies > 1) | 535 | if (conf->far_copies > 1) |
567 | new_distance = r10_bio->devs[nslot].addr; | 536 | new_distance = r10_bio->devs[slot].addr; |
568 | else | 537 | else |
569 | new_distance = abs(r10_bio->devs[nslot].addr - | 538 | new_distance = abs(r10_bio->devs[slot].addr - |
570 | conf->mirrors[ndisk].head_position); | 539 | conf->mirrors[disk].head_position); |
571 | if (new_distance < current_distance) { | 540 | if (new_distance < best_dist) { |
572 | current_distance = new_distance; | 541 | best_dist = new_distance; |
573 | disk = ndisk; | 542 | best_slot = slot; |
574 | slot = nslot; | ||
575 | } | 543 | } |
576 | } | 544 | } |
545 | if (slot == conf->copies) | ||
546 | slot = best_slot; | ||
577 | 547 | ||
578 | rb_out: | 548 | if (slot >= 0) { |
579 | r10_bio->read_slot = slot; | 549 | disk = r10_bio->devs[slot].devnum; |
580 | /* conf->next_seq_sect = this_sector + sectors;*/ | 550 | rdev = rcu_dereference(conf->mirrors[disk].rdev); |
581 | 551 | if (!rdev) | |
582 | if (disk >= 0 && (rdev=rcu_dereference(conf->mirrors[disk].rdev))!= NULL) | 552 | goto retry; |
583 | atomic_inc(&conf->mirrors[disk].rdev->nr_pending); | 553 | atomic_inc(&rdev->nr_pending); |
584 | else | 554 | if (test_bit(Faulty, &rdev->flags)) { |
555 | /* Cannot risk returning a device that failed | ||
556 | * before we inc'ed nr_pending | ||
557 | */ | ||
558 | rdev_dec_pending(rdev, conf->mddev); | ||
559 | goto retry; | ||
560 | } | ||
561 | r10_bio->read_slot = slot; | ||
562 | } else | ||
585 | disk = -1; | 563 | disk = -1; |
586 | rcu_read_unlock(); | 564 | rcu_read_unlock(); |
587 | 565 | ||