aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/ctree.h3
-rw-r--r--fs/btrfs/disk-io.c9
-rw-r--r--fs/btrfs/free-space-tree.c2
-rw-r--r--include/uapi/linux/btrfs.h12
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)