diff options
| -rw-r--r-- | fs/btrfs/ctree.h | 3 | ||||
| -rw-r--r-- | fs/btrfs/disk-io.c | 9 | ||||
| -rw-r--r-- | fs/btrfs/free-space-tree.c | 2 | ||||
| -rw-r--r-- | include/uapi/linux/btrfs.h | 12 |
4 files changed, 24 insertions, 2 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 33fe03551105..791e47ce9d27 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
| @@ -251,7 +251,8 @@ struct btrfs_super_block { | |||
| 251 | #define BTRFS_FEATURE_COMPAT_SAFE_CLEAR 0ULL | 251 | #define BTRFS_FEATURE_COMPAT_SAFE_CLEAR 0ULL |
| 252 | 252 | ||
| 253 | #define BTRFS_FEATURE_COMPAT_RO_SUPP \ | 253 | #define BTRFS_FEATURE_COMPAT_RO_SUPP \ |
| 254 | (BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE) | 254 | (BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE | \ |
| 255 | BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE_VALID) | ||
| 255 | 256 | ||
| 256 | #define BTRFS_FEATURE_COMPAT_RO_SAFE_SET 0ULL | 257 | #define BTRFS_FEATURE_COMPAT_RO_SAFE_SET 0ULL |
| 257 | #define BTRFS_FEATURE_COMPAT_RO_SAFE_CLEAR 0ULL | 258 | #define BTRFS_FEATURE_COMPAT_RO_SAFE_CLEAR 0ULL |
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) { |
diff --git a/fs/btrfs/free-space-tree.c b/fs/btrfs/free-space-tree.c index 8fd85bfbe2da..ea605ffd0e03 100644 --- a/fs/btrfs/free-space-tree.c +++ b/fs/btrfs/free-space-tree.c | |||
| @@ -1182,6 +1182,7 @@ int btrfs_create_free_space_tree(struct btrfs_fs_info *fs_info) | |||
| 1182 | } | 1182 | } |
| 1183 | 1183 | ||
| 1184 | btrfs_set_fs_compat_ro(fs_info, FREE_SPACE_TREE); | 1184 | btrfs_set_fs_compat_ro(fs_info, FREE_SPACE_TREE); |
| 1185 | btrfs_set_fs_compat_ro(fs_info, FREE_SPACE_TREE_VALID); | ||
| 1185 | fs_info->creating_free_space_tree = 0; | 1186 | fs_info->creating_free_space_tree = 0; |
| 1186 | 1187 | ||
| 1187 | ret = btrfs_commit_transaction(trans, tree_root); | 1188 | ret = btrfs_commit_transaction(trans, tree_root); |
| @@ -1250,6 +1251,7 @@ int btrfs_clear_free_space_tree(struct btrfs_fs_info *fs_info) | |||
| 1250 | return PTR_ERR(trans); | 1251 | return PTR_ERR(trans); |
| 1251 | 1252 | ||
| 1252 | btrfs_clear_fs_compat_ro(fs_info, FREE_SPACE_TREE); | 1253 | btrfs_clear_fs_compat_ro(fs_info, FREE_SPACE_TREE); |
| 1254 | btrfs_clear_fs_compat_ro(fs_info, FREE_SPACE_TREE_VALID); | ||
| 1253 | fs_info->free_space_root = NULL; | 1255 | fs_info->free_space_root = NULL; |
| 1254 | 1256 | ||
| 1255 | ret = clear_free_space_tree(trans, free_space_root); | 1257 | ret = clear_free_space_tree(trans, free_space_root); |
diff --git a/include/uapi/linux/btrfs.h b/include/uapi/linux/btrfs.h index ac5eacd3055b..db4c253f8011 100644 --- a/include/uapi/linux/btrfs.h +++ b/include/uapi/linux/btrfs.h | |||
| @@ -239,7 +239,17 @@ struct btrfs_ioctl_fs_info_args { | |||
| 239 | * Used by: | 239 | * Used by: |
| 240 | * struct btrfs_ioctl_feature_flags | 240 | * struct btrfs_ioctl_feature_flags |
| 241 | */ | 241 | */ |
| 242 | #define BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE (1ULL << 0) | 242 | #define BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE (1ULL << 0) |
| 243 | /* | ||
| 244 | * Older kernels (< 4.9) on big-endian systems produced broken free space tree | ||
| 245 | * bitmaps, and btrfs-progs also used to corrupt the free space tree (versions | ||
| 246 | * < 4.7.3). If this bit is clear, then the free space tree cannot be trusted. | ||
| 247 | * btrfs-progs can also intentionally clear this bit to ask the kernel to | ||
| 248 | * rebuild the free space tree, however this might not work on older kernels | ||
| 249 | * that do not know about this bit. If not sure, clear the cache manually on | ||
| 250 | * first mount when booting older kernel versions. | ||
| 251 | */ | ||
| 252 | #define BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE_VALID (1ULL << 1) | ||
| 243 | 253 | ||
| 244 | #define BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF (1ULL << 0) | 254 | #define BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF (1ULL << 0) |
| 245 | #define BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL (1ULL << 1) | 255 | #define BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL (1ULL << 1) |
