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>
This commit is contained in:
@@ -488,13 +488,19 @@ static int raid10_mergeable_bvec(struct request_queue *q,
|
|||||||
static int read_balance(conf_t *conf, r10bio_t *r10_bio)
|
static int read_balance(conf_t *conf, r10bio_t *r10_bio)
|
||||||
{
|
{
|
||||||
const sector_t this_sector = r10_bio->sector;
|
const sector_t this_sector = r10_bio->sector;
|
||||||
int disk, slot, nslot;
|
int disk, slot;
|
||||||
const int sectors = r10_bio->sectors;
|
const int sectors = r10_bio->sectors;
|
||||||
sector_t new_distance, current_distance;
|
sector_t new_distance, best_dist;
|
||||||
mdk_rdev_t *rdev;
|
mdk_rdev_t *rdev;
|
||||||
|
int do_balance;
|
||||||
|
int best_slot;
|
||||||
|
|
||||||
raid10_find_phys(conf, r10_bio);
|
raid10_find_phys(conf, r10_bio);
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
|
retry:
|
||||||
|
best_slot = -1;
|
||||||
|
best_dist = MaxSector;
|
||||||
|
do_balance = 1;
|
||||||
/*
|
/*
|
||||||
* Check if we can balance. We can balance on the whole
|
* Check if we can balance. We can balance on the whole
|
||||||
* device if no resync is going on (recovery is ok), or below
|
* 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)
|
|||||||
* above the resync window.
|
* above the resync window.
|
||||||
*/
|
*/
|
||||||
if (conf->mddev->recovery_cp < MaxSector
|
if (conf->mddev->recovery_cp < MaxSector
|
||||||
&& (this_sector + sectors >= conf->next_resync)) {
|
&& (this_sector + sectors >= conf->next_resync))
|
||||||
/* make sure that disk is operational */
|
do_balance = 0;
|
||||||
slot = 0;
|
|
||||||
disk = r10_bio->devs[slot].devnum;
|
|
||||||
|
|
||||||
while ((rdev = rcu_dereference(conf->mirrors[disk].rdev)) == NULL ||
|
for (slot = 0; slot < conf->copies ; slot++) {
|
||||||
r10_bio->devs[slot].bio == IO_BLOCKED ||
|
if (r10_bio->devs[slot].bio == IO_BLOCKED)
|
||||||
!test_bit(In_sync, &rdev->flags)) {
|
|
||||||
slot++;
|
|
||||||
if (slot == conf->copies) {
|
|
||||||
slot = 0;
|
|
||||||
disk = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
disk = r10_bio->devs[slot].devnum;
|
|
||||||
}
|
|
||||||
goto rb_out;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* make sure the disk is operational */
|
|
||||||
slot = 0;
|
|
||||||
disk = r10_bio->devs[slot].devnum;
|
|
||||||
while ((rdev=rcu_dereference(conf->mirrors[disk].rdev)) == NULL ||
|
|
||||||
r10_bio->devs[slot].bio == IO_BLOCKED ||
|
|
||||||
!test_bit(In_sync, &rdev->flags)) {
|
|
||||||
slot ++;
|
|
||||||
if (slot == conf->copies) {
|
|
||||||
disk = -1;
|
|
||||||
goto rb_out;
|
|
||||||
}
|
|
||||||
disk = r10_bio->devs[slot].devnum;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
current_distance = abs(r10_bio->devs[slot].addr -
|
|
||||||
conf->mirrors[disk].head_position);
|
|
||||||
|
|
||||||
/* Find the disk whose head is closest,
|
|
||||||
* or - for far > 1 - find the closest to partition beginning */
|
|
||||||
|
|
||||||
for (nslot = slot; nslot < conf->copies; nslot++) {
|
|
||||||
int ndisk = r10_bio->devs[nslot].devnum;
|
|
||||||
|
|
||||||
|
|
||||||
if ((rdev=rcu_dereference(conf->mirrors[ndisk].rdev)) == NULL ||
|
|
||||||
r10_bio->devs[nslot].bio == IO_BLOCKED ||
|
|
||||||
!test_bit(In_sync, &rdev->flags))
|
|
||||||
continue;
|
continue;
|
||||||
|
disk = r10_bio->devs[slot].devnum;
|
||||||
|
rdev = rcu_dereference(conf->mirrors[disk].rdev);
|
||||||
|
if (rdev == NULL)
|
||||||
|
continue;
|
||||||
|
if (!test_bit(In_sync, &rdev->flags))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!do_balance)
|
||||||
|
break;
|
||||||
|
|
||||||
/* This optimisation is debatable, and completely destroys
|
/* This optimisation is debatable, and completely destroys
|
||||||
* sequential read speed for 'far copies' arrays. So only
|
* sequential read speed for 'far copies' arrays. So only
|
||||||
* keep it for 'near' arrays, and review those later.
|
* keep it for 'near' arrays, and review those later.
|
||||||
*/
|
*/
|
||||||
if (conf->near_copies > 1 && !atomic_read(&rdev->nr_pending)) {
|
if (conf->near_copies > 1 && !atomic_read(&rdev->nr_pending))
|
||||||
disk = ndisk;
|
|
||||||
slot = nslot;
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
/* for far > 1 always use the lowest address */
|
/* for far > 1 always use the lowest address */
|
||||||
if (conf->far_copies > 1)
|
if (conf->far_copies > 1)
|
||||||
new_distance = r10_bio->devs[nslot].addr;
|
new_distance = r10_bio->devs[slot].addr;
|
||||||
else
|
else
|
||||||
new_distance = abs(r10_bio->devs[nslot].addr -
|
new_distance = abs(r10_bio->devs[slot].addr -
|
||||||
conf->mirrors[ndisk].head_position);
|
conf->mirrors[disk].head_position);
|
||||||
if (new_distance < current_distance) {
|
if (new_distance < best_dist) {
|
||||||
current_distance = new_distance;
|
best_dist = new_distance;
|
||||||
disk = ndisk;
|
best_slot = slot;
|
||||||
slot = nslot;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (slot == conf->copies)
|
||||||
|
slot = best_slot;
|
||||||
|
|
||||||
rb_out:
|
if (slot >= 0) {
|
||||||
r10_bio->read_slot = slot;
|
disk = r10_bio->devs[slot].devnum;
|
||||||
/* conf->next_seq_sect = this_sector + sectors;*/
|
rdev = rcu_dereference(conf->mirrors[disk].rdev);
|
||||||
|
if (!rdev)
|
||||||
if (disk >= 0 && (rdev=rcu_dereference(conf->mirrors[disk].rdev))!= NULL)
|
goto retry;
|
||||||
atomic_inc(&conf->mirrors[disk].rdev->nr_pending);
|
atomic_inc(&rdev->nr_pending);
|
||||||
else
|
if (test_bit(Faulty, &rdev->flags)) {
|
||||||
|
/* Cannot risk returning a device that failed
|
||||||
|
* before we inc'ed nr_pending
|
||||||
|
*/
|
||||||
|
rdev_dec_pending(rdev, conf->mddev);
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
r10_bio->read_slot = slot;
|
||||||
|
} else
|
||||||
disk = -1;
|
disk = -1;
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user