diff options
author | NeilBrown <neilb@suse.de> | 2010-09-06 00:10:08 -0400 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2010-10-29 01:40:33 -0400 |
commit | f3ac8bf7ce1c5abd763ea762e95d1cdcf7799372 (patch) | |
tree | bb903d4265520d5c96a9ee08557dd7f92c1f08df /drivers/md/raid1.c | |
parent | 046abeede717909feec38587d667cde1fc6c459c (diff) |
md: tidy up device searches in read_balance.
The code for searching through the device list to read-balance in
raid1 is rather clumsy and hard to follow. Try to simplify it a bit.
No important functionality change here.
Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'drivers/md/raid1.c')
-rw-r--r-- | drivers/md/raid1.c | 92 |
1 files changed, 36 insertions, 56 deletions
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index a0322db4d355..45f8324196ec 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c | |||
@@ -419,11 +419,13 @@ static void raid1_end_write_request(struct bio *bio, int error) | |||
419 | static int read_balance(conf_t *conf, r1bio_t *r1_bio) | 419 | static int read_balance(conf_t *conf, r1bio_t *r1_bio) |
420 | { | 420 | { |
421 | const sector_t this_sector = r1_bio->sector; | 421 | const sector_t this_sector = r1_bio->sector; |
422 | int new_disk = conf->last_used, disk = new_disk; | ||
423 | int wonly_disk = -1; | ||
424 | const int sectors = r1_bio->sectors; | 422 | const int sectors = r1_bio->sectors; |
423 | int new_disk = -1; | ||
424 | int start_disk; | ||
425 | int i; | ||
425 | sector_t new_distance, current_distance; | 426 | sector_t new_distance, current_distance; |
426 | mdk_rdev_t *rdev; | 427 | mdk_rdev_t *rdev; |
428 | int choose_first; | ||
427 | 429 | ||
428 | rcu_read_lock(); | 430 | rcu_read_lock(); |
429 | /* | 431 | /* |
@@ -434,54 +436,33 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio) | |||
434 | retry: | 436 | retry: |
435 | if (conf->mddev->recovery_cp < MaxSector && | 437 | if (conf->mddev->recovery_cp < MaxSector && |
436 | (this_sector + sectors >= conf->next_resync)) { | 438 | (this_sector + sectors >= conf->next_resync)) { |
437 | /* Choose the first operational device, for consistancy */ | 439 | choose_first = 1; |
438 | new_disk = 0; | 440 | start_disk = 0; |
439 | 441 | } else { | |
440 | for (rdev = rcu_dereference(conf->mirrors[new_disk].rdev); | 442 | choose_first = 0; |
441 | r1_bio->bios[new_disk] == IO_BLOCKED || | 443 | start_disk = conf->last_used; |
442 | !rdev || !test_bit(In_sync, &rdev->flags) | ||
443 | || test_bit(WriteMostly, &rdev->flags); | ||
444 | rdev = rcu_dereference(conf->mirrors[++new_disk].rdev)) { | ||
445 | |||
446 | if (rdev && test_bit(In_sync, &rdev->flags) && | ||
447 | r1_bio->bios[new_disk] != IO_BLOCKED) | ||
448 | wonly_disk = new_disk; | ||
449 | |||
450 | if (new_disk == conf->raid_disks - 1) { | ||
451 | new_disk = wonly_disk; | ||
452 | break; | ||
453 | } | ||
454 | } | ||
455 | goto rb_out; | ||
456 | } | 444 | } |
457 | 445 | ||
458 | |||
459 | /* make sure the disk is operational */ | 446 | /* make sure the disk is operational */ |
460 | for (rdev = rcu_dereference(conf->mirrors[new_disk].rdev); | 447 | for (i = 0 ; i < conf->raid_disks ; i++) { |
461 | r1_bio->bios[new_disk] == IO_BLOCKED || | 448 | int disk = start_disk + i; |
462 | !rdev || !test_bit(In_sync, &rdev->flags) || | 449 | if (disk >= conf->raid_disks) |
463 | test_bit(WriteMostly, &rdev->flags); | 450 | disk -= conf->raid_disks; |
464 | rdev = rcu_dereference(conf->mirrors[new_disk].rdev)) { | 451 | |
465 | 452 | rdev = rcu_dereference(conf->mirrors[disk].rdev); | |
466 | if (rdev && test_bit(In_sync, &rdev->flags) && | 453 | if (r1_bio->bios[disk] == IO_BLOCKED |
467 | r1_bio->bios[new_disk] != IO_BLOCKED) | 454 | || rdev == NULL |
468 | wonly_disk = new_disk; | 455 | || !test_bit(In_sync, &rdev->flags)) |
469 | 456 | continue; | |
470 | if (new_disk <= 0) | 457 | |
471 | new_disk = conf->raid_disks; | 458 | new_disk = disk; |
472 | new_disk--; | 459 | if (!test_bit(WriteMostly, &rdev->flags)) |
473 | if (new_disk == disk) { | ||
474 | new_disk = wonly_disk; | ||
475 | break; | 460 | break; |
476 | } | ||
477 | } | 461 | } |
478 | 462 | ||
479 | if (new_disk < 0) | 463 | if (new_disk < 0 || choose_first) |
480 | goto rb_out; | 464 | goto rb_out; |
481 | 465 | ||
482 | disk = new_disk; | ||
483 | /* now disk == new_disk == starting point for search */ | ||
484 | |||
485 | /* | 466 | /* |
486 | * Don't change to another disk for sequential reads: | 467 | * Don't change to another disk for sequential reads: |
487 | */ | 468 | */ |
@@ -490,20 +471,21 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio) | |||
490 | if (this_sector == conf->mirrors[new_disk].head_position) | 471 | if (this_sector == conf->mirrors[new_disk].head_position) |
491 | goto rb_out; | 472 | goto rb_out; |
492 | 473 | ||
493 | current_distance = abs(this_sector - conf->mirrors[disk].head_position); | 474 | current_distance = abs(this_sector |
475 | - conf->mirrors[new_disk].head_position); | ||
494 | 476 | ||
495 | /* Find the disk whose head is closest */ | 477 | /* look for a better disk - i.e. head is closer */ |
496 | 478 | start_disk = new_disk; | |
497 | do { | 479 | for (i = 1; i < conf->raid_disks; i++) { |
498 | if (disk <= 0) | 480 | int disk = start_disk + 1; |
499 | disk = conf->raid_disks; | 481 | if (disk >= conf->raid_disks) |
500 | disk--; | 482 | disk -= conf->raid_disks; |
501 | 483 | ||
502 | rdev = rcu_dereference(conf->mirrors[disk].rdev); | 484 | rdev = rcu_dereference(conf->mirrors[disk].rdev); |
503 | 485 | if (r1_bio->bios[disk] == IO_BLOCKED | |
504 | if (!rdev || r1_bio->bios[disk] == IO_BLOCKED || | 486 | || rdev == NULL |
505 | !test_bit(In_sync, &rdev->flags) || | 487 | || !test_bit(In_sync, &rdev->flags) |
506 | test_bit(WriteMostly, &rdev->flags)) | 488 | || test_bit(WriteMostly, &rdev->flags)) |
507 | continue; | 489 | continue; |
508 | 490 | ||
509 | if (!atomic_read(&rdev->nr_pending)) { | 491 | if (!atomic_read(&rdev->nr_pending)) { |
@@ -515,11 +497,9 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio) | |||
515 | current_distance = new_distance; | 497 | current_distance = new_distance; |
516 | new_disk = disk; | 498 | new_disk = disk; |
517 | } | 499 | } |
518 | } while (disk != conf->last_used); | 500 | } |
519 | 501 | ||
520 | rb_out: | 502 | rb_out: |
521 | |||
522 | |||
523 | if (new_disk >= 0) { | 503 | if (new_disk >= 0) { |
524 | rdev = rcu_dereference(conf->mirrors[new_disk].rdev); | 504 | rdev = rcu_dereference(conf->mirrors[new_disk].rdev); |
525 | if (!rdev) | 505 | if (!rdev) |