aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/raid5.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2011-12-22 18:17:52 -0500
committerNeilBrown <neilb@suse.de>2011-12-22 18:17:52 -0500
commit671488cc25f7c194c7c7a9f258bab1df17a6ff69 (patch)
tree00bec63c7789dbf7439418ee903490d6ee076a70 /drivers/md/raid5.c
parent2d78f8c451785f030ac1676a18691896b59c69d8 (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.c15
1 files changed, 13 insertions, 2 deletions
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 6b9fc58e8f2..94bc35ba4c8 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