aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/volumes.c
diff options
context:
space:
mode:
authorStefan Behrens <sbehrens@giantdisaster.de>2012-11-06 08:52:18 -0500
committerJosef Bacik <jbacik@fusionio.com>2012-12-12 17:15:44 -0500
commit30d9861ff9520e2a112eae71029bc9f7e915a441 (patch)
treeba826aaeee18acacd5871fc47774abc25f072e62 /fs/btrfs/volumes.c
parent472262f35a6b3407e761b700d74c53530e5f144d (diff)
Btrfs: optionally avoid reads from device replace source drive
It is desirable to be able to configure the device replace procedure to avoid reading the source drive (the one to be copied) whenever possible. This is useful when the number of read errors on this disk is high, because it would delay the copy procedure alot. Therefore there is an option to avoid reading from the source disk unless the repair procedure really needs to access it. The regular read req asks for mapping the block with mirror_num == 0, in this case the source disk is avoided whenever possible. The repair code selects the mirror_num explicitly (mirror_num != 0), this case is not changed by this commit. Signed-off-by: Stefan Behrens <sbehrens@giantdisaster.de> Signed-off-by: Chris Mason <chris.mason@fusionio.com>
Diffstat (limited to 'fs/btrfs/volumes.c')
-rw-r--r--fs/btrfs/volumes.c46
1 files changed, 35 insertions, 11 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 4d3bf187ab52..e2e01a327108 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -4007,16 +4007,37 @@ int btrfs_num_copies(struct btrfs_fs_info *fs_info, u64 logical, u64 len)
4007 return ret; 4007 return ret;
4008} 4008}
4009 4009
4010static int find_live_mirror(struct map_lookup *map, int first, int num, 4010static int find_live_mirror(struct btrfs_fs_info *fs_info,
4011 int optimal) 4011 struct map_lookup *map, int first, int num,
4012 int optimal, int dev_replace_is_ongoing)
4012{ 4013{
4013 int i; 4014 int i;
4014 if (map->stripes[optimal].dev->bdev) 4015 int tolerance;
4015 return optimal; 4016 struct btrfs_device *srcdev;
4016 for (i = first; i < first + num; i++) { 4017
4017 if (map->stripes[i].dev->bdev) 4018 if (dev_replace_is_ongoing &&
4018 return i; 4019 fs_info->dev_replace.cont_reading_from_srcdev_mode ==
4020 BTRFS_DEV_REPLACE_ITEM_CONT_READING_FROM_SRCDEV_MODE_AVOID)
4021 srcdev = fs_info->dev_replace.srcdev;
4022 else
4023 srcdev = NULL;
4024
4025 /*
4026 * try to avoid the drive that is the source drive for a
4027 * dev-replace procedure, only choose it if no other non-missing
4028 * mirror is available
4029 */
4030 for (tolerance = 0; tolerance < 2; tolerance++) {
4031 if (map->stripes[optimal].dev->bdev &&
4032 (tolerance || map->stripes[optimal].dev != srcdev))
4033 return optimal;
4034 for (i = first; i < first + num; i++) {
4035 if (map->stripes[i].dev->bdev &&
4036 (tolerance || map->stripes[i].dev != srcdev))
4037 return i;
4038 }
4019 } 4039 }
4040
4020 /* we couldn't find one that doesn't fail. Just return something 4041 /* we couldn't find one that doesn't fail. Just return something
4021 * and the io error handling code will clean up eventually 4042 * and the io error handling code will clean up eventually
4022 */ 4043 */
@@ -4116,9 +4137,10 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw,
4116 else if (mirror_num) 4137 else if (mirror_num)
4117 stripe_index = mirror_num - 1; 4138 stripe_index = mirror_num - 1;
4118 else { 4139 else {
4119 stripe_index = find_live_mirror(map, 0, 4140 stripe_index = find_live_mirror(fs_info, map, 0,
4120 map->num_stripes, 4141 map->num_stripes,
4121 current->pid % map->num_stripes); 4142 current->pid % map->num_stripes,
4143 dev_replace_is_ongoing);
4122 mirror_num = stripe_index + 1; 4144 mirror_num = stripe_index + 1;
4123 } 4145 }
4124 4146
@@ -4147,9 +4169,11 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw,
4147 stripe_index += mirror_num - 1; 4169 stripe_index += mirror_num - 1;
4148 else { 4170 else {
4149 int old_stripe_index = stripe_index; 4171 int old_stripe_index = stripe_index;
4150 stripe_index = find_live_mirror(map, stripe_index, 4172 stripe_index = find_live_mirror(fs_info, map,
4173 stripe_index,
4151 map->sub_stripes, stripe_index + 4174 map->sub_stripes, stripe_index +
4152 current->pid % map->sub_stripes); 4175 current->pid % map->sub_stripes,
4176 dev_replace_is_ongoing);
4153 mirror_num = stripe_index - old_stripe_index + 1; 4177 mirror_num = stripe_index - old_stripe_index + 1;
4154 } 4178 }
4155 } else { 4179 } else {