summaryrefslogtreecommitdiffstats
path: root/fs/btrfs/disk-io.c
diff options
context:
space:
mode:
authorOmar Sandoval <osandov@fb.com>2016-09-22 20:24:22 -0400
committerDavid Sterba <dsterba@suse.com>2016-10-03 12:52:14 -0400
commit6675df311db87aa2107a04ef97e19420953cbace (patch)
tree0c1afd7c2acb7bcb767c949984203c6f96ac4184 /fs/btrfs/disk-io.c
parentf8d468a15c22b954b379aa0c74914d5068448fb1 (diff)
Btrfs: catch invalid free space trees
There are two separate issues that can lead to corrupted free space trees. 1. The free space tree bitmaps had an endianness issue on big-endian systems which is fixed by an earlier patch in this series. 2. btrfs-progs before v4.7.3 modified filesystems without updating the free space tree. To catch both of these issues at once, we need to force the free space tree to be rebuilt. To do so, add a FREE_SPACE_TREE_VALID compat_ro bit. If the bit isn't set, we know that it was either produced by a broken big-endian kernel or may have been corrupted by btrfs-progs. This also provides us with a way to add rudimentary read-write support for the free space tree to btrfs-progs: it can just clear this bit and have the kernel rebuild the free space tree. Cc: stable@vger.kernel.org # 4.5+ Tested-by: Holger Hoffstätte <holger@applied-asynchrony.com> Tested-by: Chandan Rajendra <chandan@linux.vnet.ibm.com> Signed-off-by: Omar Sandoval <osandov@fb.com> Signed-off-by: David Sterba <dsterba@suse.com>
Diffstat (limited to 'fs/btrfs/disk-io.c')
-rw-r--r--fs/btrfs/disk-io.c9
1 files changed, 9 insertions, 0 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index c0bfc6ce5f06..3dede6d53bad 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -2566,6 +2566,7 @@ int open_ctree(struct super_block *sb,
2566 int num_backups_tried = 0; 2566 int num_backups_tried = 0;
2567 int backup_index = 0; 2567 int backup_index = 0;
2568 int max_active; 2568 int max_active;
2569 int clear_free_space_tree = 0;
2569 2570
2570 tree_root = fs_info->tree_root = btrfs_alloc_root(fs_info, GFP_KERNEL); 2571 tree_root = fs_info->tree_root = btrfs_alloc_root(fs_info, GFP_KERNEL);
2571 chunk_root = fs_info->chunk_root = btrfs_alloc_root(fs_info, GFP_KERNEL); 2572 chunk_root = fs_info->chunk_root = btrfs_alloc_root(fs_info, GFP_KERNEL);
@@ -3131,6 +3132,14 @@ retry_root_backup:
3131 3132
3132 if (btrfs_test_opt(fs_info, CLEAR_CACHE) && 3133 if (btrfs_test_opt(fs_info, CLEAR_CACHE) &&
3133 btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE)) { 3134 btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE)) {
3135 clear_free_space_tree = 1;
3136 } else if (btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE) &&
3137 !btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE_VALID)) {
3138 btrfs_warn(fs_info, "free space tree is invalid");
3139 clear_free_space_tree = 1;
3140 }
3141
3142 if (clear_free_space_tree) {
3134 btrfs_info(fs_info, "clearing free space tree"); 3143 btrfs_info(fs_info, "clearing free space tree");
3135 ret = btrfs_clear_free_space_tree(fs_info); 3144 ret = btrfs_clear_free_space_tree(fs_info);
3136 if (ret) { 3145 if (ret) {