aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/volumes.c
diff options
context:
space:
mode:
authorMiao Xie <miaox@cn.fujitsu.com>2014-07-03 06:22:13 -0400
committerChris Mason <clm@fb.com>2014-09-17 16:37:27 -0400
commitd20983b40e828fdca920b3d678544c6a0967a446 (patch)
treebfcd3d752e12bb727701250fdf58cb5f3f0abebc /fs/btrfs/volumes.c
parent47059d930f0e002ff851beea87d738146804726d (diff)
Btrfs: fix writing data into the seed filesystem
If we mounted a seed filesystem with degraded option, and then added a new device into the seed filesystem, then we found adding device failed because of the IO failure. Steps to reproduce: # mkfs.btrfs -d raid1 -m raid1 <dev0> <dev1> # btrfstune -S 1 <dev0> # mount <dev0> -o degraded <mnt> # btrfs device add -f <dev2> <mnt> It is because the original didn't set the chunk on the seed device to be read-only if the degraded flag was set. It was introduced by patch f48b90756, which fixed the problem the raid1 filesystem became read-only after one device of it was missing. But this fix method was not right, we should set the read-only flag according to the number of the missing devices, not the degraded mount option, if the number of the missing devices is less than the max error number that the profile of the chunk tolerates, we don't set it to be read-only. Cc: Josef Bacik <jbacik@fb.com> Signed-off-by: Miao Xie <miaox@cn.fujitsu.com> Reviewed-by: Liu Bo <bo.li.liu@oracle.com> Signed-off-by: Chris Mason <clm@fb.com>
Diffstat (limited to 'fs/btrfs/volumes.c')
-rw-r--r--fs/btrfs/volumes.c52
1 files changed, 36 insertions, 16 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index a7a3863e3807..48c357223e56 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -4583,12 +4583,31 @@ out:
4583 return ret; 4583 return ret;
4584} 4584}
4585 4585
4586static inline int btrfs_chunk_max_errors(struct map_lookup *map)
4587{
4588 int max_errors;
4589
4590 if (map->type & (BTRFS_BLOCK_GROUP_RAID1 |
4591 BTRFS_BLOCK_GROUP_RAID10 |
4592 BTRFS_BLOCK_GROUP_RAID5 |
4593 BTRFS_BLOCK_GROUP_DUP)) {
4594 max_errors = 1;
4595 } else if (map->type & BTRFS_BLOCK_GROUP_RAID6) {
4596 max_errors = 2;
4597 } else {
4598 max_errors = 0;
4599 }
4600
4601 return max_errors;
4602}
4603
4586int btrfs_chunk_readonly(struct btrfs_root *root, u64 chunk_offset) 4604int btrfs_chunk_readonly(struct btrfs_root *root, u64 chunk_offset)
4587{ 4605{
4588 struct extent_map *em; 4606 struct extent_map *em;
4589 struct map_lookup *map; 4607 struct map_lookup *map;
4590 struct btrfs_mapping_tree *map_tree = &root->fs_info->mapping_tree; 4608 struct btrfs_mapping_tree *map_tree = &root->fs_info->mapping_tree;
4591 int readonly = 0; 4609 int readonly = 0;
4610 int miss_ndevs = 0;
4592 int i; 4611 int i;
4593 4612
4594 read_lock(&map_tree->map_tree.lock); 4613 read_lock(&map_tree->map_tree.lock);
@@ -4597,18 +4616,27 @@ int btrfs_chunk_readonly(struct btrfs_root *root, u64 chunk_offset)
4597 if (!em) 4616 if (!em)
4598 return 1; 4617 return 1;
4599 4618
4600 if (btrfs_test_opt(root, DEGRADED)) {
4601 free_extent_map(em);
4602 return 0;
4603 }
4604
4605 map = (struct map_lookup *)em->bdev; 4619 map = (struct map_lookup *)em->bdev;
4606 for (i = 0; i < map->num_stripes; i++) { 4620 for (i = 0; i < map->num_stripes; i++) {
4621 if (map->stripes[i].dev->missing) {
4622 miss_ndevs++;
4623 continue;
4624 }
4625
4607 if (!map->stripes[i].dev->writeable) { 4626 if (!map->stripes[i].dev->writeable) {
4608 readonly = 1; 4627 readonly = 1;
4609 break; 4628 goto end;
4610 } 4629 }
4611 } 4630 }
4631
4632 /*
4633 * If the number of missing devices is larger than max errors,
4634 * we can not write the data into that chunk successfully, so
4635 * set it readonly.
4636 */
4637 if (miss_ndevs > btrfs_chunk_max_errors(map))
4638 readonly = 1;
4639end:
4612 free_extent_map(em); 4640 free_extent_map(em);
4613 return readonly; 4641 return readonly;
4614} 4642}
@@ -5219,16 +5247,8 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw,
5219 } 5247 }
5220 } 5248 }
5221 5249
5222 if (rw & (REQ_WRITE | REQ_GET_READ_MIRRORS)) { 5250 if (rw & (REQ_WRITE | REQ_GET_READ_MIRRORS))
5223 if (map->type & (BTRFS_BLOCK_GROUP_RAID1 | 5251 max_errors = btrfs_chunk_max_errors(map);
5224 BTRFS_BLOCK_GROUP_RAID10 |
5225 BTRFS_BLOCK_GROUP_RAID5 |
5226 BTRFS_BLOCK_GROUP_DUP)) {
5227 max_errors = 1;
5228 } else if (map->type & BTRFS_BLOCK_GROUP_RAID6) {
5229 max_errors = 2;
5230 }
5231 }
5232 5252
5233 if (dev_replace_is_ongoing && (rw & (REQ_WRITE | REQ_DISCARD)) && 5253 if (dev_replace_is_ongoing && (rw & (REQ_WRITE | REQ_DISCARD)) &&
5234 dev_replace->tgtdev != NULL) { 5254 dev_replace->tgtdev != NULL) {