aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/raid1.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2010-09-06 00:10:08 -0400
committerNeilBrown <neilb@suse.de>2010-10-29 01:40:33 -0400
commitf3ac8bf7ce1c5abd763ea762e95d1cdcf7799372 (patch)
treebb903d4265520d5c96a9ee08557dd7f92c1f08df /drivers/md/raid1.c
parent046abeede717909feec38587d667cde1fc6c459c (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.c92
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)
419static int read_balance(conf_t *conf, r1bio_t *r1_bio) 419static 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)