diff options
author | NeilBrown <neilb@suse.de> | 2011-12-22 18:17:52 -0500 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2011-12-22 18:17:52 -0500 |
commit | 671488cc25f7c194c7c7a9f258bab1df17a6ff69 (patch) | |
tree | 00bec63c7789dbf7439418ee903490d6ee076a70 /drivers/md/raid5.c | |
parent | 2d78f8c451785f030ac1676a18691896b59c69d8 (diff) |
md/raid5: allow each slot to have an extra replacement device
Just enhance data structures to record a second device per slot to be
used as a 'replacement' device, replacing the original.
We also have a second bio in each slot in each stripe_head. This will
only be used when writing to the array - we need to write to both the
original and the replacement at the same time, so will need two bios.
For now, only try using the replacement drive for aligned-reads.
In this case, we prefer the replacement if it has been recovered far
enough, otherwise use the original.
This includes a small enhancement. Previously we would only do
aligned reads if the target device was fully recovered. Now we also
do them if it has recovered far enough.
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'drivers/md/raid5.c')
-rw-r--r-- | drivers/md/raid5.c | 15 |
1 files changed, 13 insertions, 2 deletions
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 6b9fc58e8f2d..94bc35ba4c81 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
@@ -3594,6 +3594,7 @@ static int chunk_aligned_read(struct mddev *mddev, struct bio * raid_bio) | |||
3594 | int dd_idx; | 3594 | int dd_idx; |
3595 | struct bio* align_bi; | 3595 | struct bio* align_bi; |
3596 | struct md_rdev *rdev; | 3596 | struct md_rdev *rdev; |
3597 | sector_t end_sector; | ||
3597 | 3598 | ||
3598 | if (!in_chunk_boundary(mddev, raid_bio)) { | 3599 | if (!in_chunk_boundary(mddev, raid_bio)) { |
3599 | pr_debug("chunk_aligned_read : non aligned\n"); | 3600 | pr_debug("chunk_aligned_read : non aligned\n"); |
@@ -3618,9 +3619,19 @@ static int chunk_aligned_read(struct mddev *mddev, struct bio * raid_bio) | |||
3618 | 0, | 3619 | 0, |
3619 | &dd_idx, NULL); | 3620 | &dd_idx, NULL); |
3620 | 3621 | ||
3622 | end_sector = align_bi->bi_sector + (align_bi->bi_size >> 9); | ||
3621 | rcu_read_lock(); | 3623 | rcu_read_lock(); |
3622 | rdev = rcu_dereference(conf->disks[dd_idx].rdev); | 3624 | rdev = rcu_dereference(conf->disks[dd_idx].replacement); |
3623 | if (rdev && test_bit(In_sync, &rdev->flags)) { | 3625 | if (!rdev || test_bit(Faulty, &rdev->flags) || |
3626 | rdev->recovery_offset < end_sector) { | ||
3627 | rdev = rcu_dereference(conf->disks[dd_idx].rdev); | ||
3628 | if (rdev && | ||
3629 | (test_bit(Faulty, &rdev->flags) || | ||
3630 | !(test_bit(In_sync, &rdev->flags) || | ||
3631 | rdev->recovery_offset >= end_sector))) | ||
3632 | rdev = NULL; | ||
3633 | } | ||
3634 | if (rdev) { | ||
3624 | sector_t first_bad; | 3635 | sector_t first_bad; |
3625 | int bad_sectors; | 3636 | int bad_sectors; |
3626 | 3637 | ||