btrfs-progs: tests: Remove misleading BCP 78 boilerplate from SHA implementation
[platform/upstream/btrfs-progs.git] / cmds-check.c
index 7a973e3..006edbd 100644 (file)
@@ -66,7 +66,6 @@ static u64 total_extent_tree_bytes = 0;
 static u64 btree_space_waste = 0;
 static u64 data_bytes_allocated = 0;
 static u64 data_bytes_referenced = 0;
-static int found_old_backref = 0;
 static LIST_HEAD(duplicate_extents);
 static LIST_HEAD(delete_items);
 static int no_holes = 0;
@@ -226,7 +225,6 @@ struct root_item_record {
        u64 last_snapshot;
        u8 level;
        u8 drop_level;
-       int level_size;
        struct btrfs_key drop_key;
 };
 
@@ -1990,8 +1988,7 @@ static void reada_walk_down(struct btrfs_root *root,
        for (i = slot; i < nritems; i++) {
                bytenr = btrfs_node_blockptr(node, i);
                ptr_gen = btrfs_node_ptr_generation(node, i);
-               readahead_tree_block(fs_info, bytenr, fs_info->nodesize,
-                               ptr_gen);
+               readahead_tree_block(fs_info, bytenr, ptr_gen);
        }
 }
 
@@ -2190,8 +2187,7 @@ static int walk_down_tree(struct btrfs_root *root, struct btrfs_path *path,
                if (!next || !btrfs_buffer_uptodate(next, ptr_gen)) {
                        free_extent_buffer(next);
                        reada_walk_down(root, cur, path->slots[*level]);
-                       next = read_tree_block(root->fs_info, bytenr,
-                                       fs_info->nodesize, ptr_gen);
+                       next = read_tree_block(root->fs_info, bytenr, ptr_gen);
                        if (!extent_buffer_uptodate(next)) {
                                struct btrfs_key node_key;
 
@@ -2304,8 +2300,7 @@ static int walk_down_tree_v2(struct btrfs_root *root, struct btrfs_path *path,
                if (!next || !btrfs_buffer_uptodate(next, ptr_gen)) {
                        free_extent_buffer(next);
                        reada_walk_down(root, cur, path->slots[*level]);
-                       next = read_tree_block(fs_info, bytenr,
-                                       fs_info->nodesize, ptr_gen);
+                       next = read_tree_block(fs_info, bytenr, ptr_gen);
                        if (!extent_buffer_uptodate(next)) {
                                struct btrfs_key node_key;
 
@@ -4055,7 +4050,7 @@ static int fs_root_objectid(u64 objectid)
        return is_fstree(objectid);
 }
 
-static int check_fs_roots(struct btrfs_root *root,
+static int check_fs_roots(struct btrfs_fs_info *fs_info,
                          struct cache_tree *root_cache)
 {
        struct btrfs_path path;
@@ -4063,7 +4058,7 @@ static int check_fs_roots(struct btrfs_root *root,
        struct walk_control wc;
        struct extent_buffer *leaf, *tree_node;
        struct btrfs_root *tmp_root;
-       struct btrfs_root *tree_root = root->fs_info->tree_root;
+       struct btrfs_root *tree_root = fs_info->tree_root;
        int ret;
        int err = 0;
 
@@ -4077,7 +4072,7 @@ static int check_fs_roots(struct btrfs_root *root,
         * reflected into the free space cache yet.
         */
        if (repair)
-               reset_cached_block_groups(root->fs_info);
+               reset_cached_block_groups(fs_info);
        memset(&wc, 0, sizeof(wc));
        cache_tree_init(&wc.shared);
        btrfs_init_path(&path);
@@ -4113,11 +4108,11 @@ again:
                    fs_root_objectid(key.objectid)) {
                        if (key.objectid == BTRFS_TREE_RELOC_OBJECTID) {
                                tmp_root = btrfs_read_fs_root_no_cache(
-                                               root->fs_info, &key);
+                                               fs_info, &key);
                        } else {
                                key.offset = (u64)-1;
                                tmp_root = btrfs_read_fs_root(
-                                               root->fs_info, &key);
+                                               fs_info, &key);
                        }
                        if (IS_ERR(tmp_root)) {
                                err = 1;
@@ -5319,6 +5314,21 @@ out:
        return err;
 }
 
+static int do_check_fs_roots(struct btrfs_fs_info *fs_info,
+                         struct cache_tree *root_cache)
+{
+       int ret;
+
+       if (!ctx.progress_enabled)
+               fprintf(stderr, "checking fs roots\n");
+       if (check_mode == CHECK_MODE_LOWMEM)
+               ret = check_fs_roots_v2(fs_info);
+       else
+               ret = check_fs_roots(fs_info, root_cache);
+
+       return ret;
+}
+
 static int all_backpointers_checked(struct extent_record *rec, int print_errs)
 {
        struct list_head *cur = rec->backrefs.next;
@@ -7653,8 +7663,7 @@ static int run_next_block(struct btrfs_root *root,
                                continue;
 
                        /* fixme, get the parent transid */
-                       readahead_tree_block(fs_info, bits[i].start,
-                                            bits[i].size, 0);
+                       readahead_tree_block(fs_info, bits[i].start, 0);
                }
        }
        *last = bits[0].start;
@@ -7683,7 +7692,7 @@ static int run_next_block(struct btrfs_root *root,
        }
 
        /* fixme, get the real parent transid */
-       buf = read_tree_block(root->fs_info, bytenr, size, gen);
+       buf = read_tree_block(root->fs_info, bytenr, gen);
        if (!extent_buffer_uptodate(buf)) {
                record_bad_block_io(root->fs_info,
                                    extent_cache, bytenr, size);
@@ -7950,11 +7959,6 @@ static int run_next_block(struct btrfs_root *root,
                total_fs_tree_bytes += buf->len;
        if (btrfs_header_owner(buf) == BTRFS_EXTENT_TREE_OBJECTID)
                total_extent_tree_bytes += buf->len;
-       if (!found_old_backref &&
-           btrfs_header_owner(buf) == BTRFS_TREE_RELOC_OBJECTID &&
-           btrfs_header_backref_rev(buf) == BTRFS_MIXED_BACKREF_REV &&
-           !btrfs_header_flag(buf, BTRFS_HEADER_FLAG_RELOC))
-               found_old_backref = 1;
 out:
        free_extent_buffer(buf);
        return ret;
@@ -9472,7 +9476,9 @@ repair_abort:
                                goto repair_abort;
                        }
 
-                       btrfs_fix_block_accounting(trans, root);
+                       ret = btrfs_fix_block_accounting(trans, root);
+                       if (ret)
+                               goto repair_abort;
                        ret = btrfs_commit_transaction(trans, root);
                        if (ret)
                                goto repair_abort;
@@ -9741,7 +9747,7 @@ static int check_devices(struct rb_root *dev_cache,
 static int add_root_item_to_list(struct list_head *head,
                                  u64 objectid, u64 bytenr, u64 last_snapshot,
                                  u8 level, u8 drop_level,
-                                 int level_size, struct btrfs_key *drop_key)
+                                 struct btrfs_key *drop_key)
 {
 
        struct root_item_record *ri_rec;
@@ -9751,7 +9757,6 @@ static int add_root_item_to_list(struct list_head *head,
        ri_rec->bytenr = bytenr;
        ri_rec->objectid = objectid;
        ri_rec->level = level;
-       ri_rec->level_size = level_size;
        ri_rec->drop_level = drop_level;
        ri_rec->last_snapshot = last_snapshot;
        if (drop_key)
@@ -9796,8 +9801,7 @@ static int deal_root_from_list(struct list_head *list,
                rec = list_entry(list->next,
                                 struct root_item_record, list);
                last = 0;
-               buf = read_tree_block(root->fs_info,
-                                     rec->bytenr, rec->level_size, 0);
+               buf = read_tree_block(root->fs_info, rec->bytenr, 0);
                if (!extent_buffer_uptodate(buf)) {
                        free_extent_buffer(buf);
                        ret = -EIO;
@@ -9841,7 +9845,7 @@ static int deal_root_from_list(struct list_head *list,
        return ret;
 }
 
-static int check_chunks_and_extents(struct btrfs_root *root)
+static int check_chunks_and_extents(struct btrfs_fs_info *fs_info)
 {
        struct rb_root dev_cache;
        struct cache_tree chunk_cache;
@@ -9866,10 +9870,11 @@ static int check_chunks_and_extents(struct btrfs_root *root)
        struct list_head dropping_trees;
        struct list_head normal_trees;
        struct btrfs_root *root1;
+       struct btrfs_root *root;
        u64 objectid;
-       u32 level_size;
        u8 level;
 
+       root = fs_info->fs_root;
        dev_cache = RB_ROOT;
        cache_tree_init(&chunk_cache);
        block_group_tree_init(&block_group_cache);
@@ -9886,10 +9891,10 @@ static int check_chunks_and_extents(struct btrfs_root *root)
        INIT_LIST_HEAD(&normal_trees);
 
        if (repair) {
-               root->fs_info->excluded_extents = &excluded_extents;
-               root->fs_info->fsck_extent_cache = &extent_cache;
-               root->fs_info->free_extent_hook = free_extent_hook;
-               root->fs_info->corrupt_blocks = &corrupt_blocks;
+               fs_info->excluded_extents = &excluded_extents;
+               fs_info->fsck_extent_cache = &extent_cache;
+               fs_info->free_extent_hook = free_extent_hook;
+               fs_info->corrupt_blocks = &corrupt_blocks;
        }
 
        bits_nr = 1024;
@@ -9905,26 +9910,23 @@ static int check_chunks_and_extents(struct btrfs_root *root)
        }
 
 again:
-       root1 = root->fs_info->tree_root;
+       root1 = fs_info->tree_root;
        level = btrfs_header_level(root1->node);
        ret = add_root_item_to_list(&normal_trees, root1->root_key.objectid,
-                                   root1->node->start, 0, level, 0,
-                                   root1->fs_info->nodesize, NULL);
+                                   root1->node->start, 0, level, 0, NULL);
        if (ret < 0)
                goto out;
-       root1 = root->fs_info->chunk_root;
+       root1 = fs_info->chunk_root;
        level = btrfs_header_level(root1->node);
        ret = add_root_item_to_list(&normal_trees, root1->root_key.objectid,
-                                   root1->node->start, 0, level, 0,
-                                   root1->fs_info->nodesize, NULL);
+                                   root1->node->start, 0, level, 0, NULL);
        if (ret < 0)
                goto out;
        btrfs_init_path(&path);
        key.offset = 0;
        key.objectid = 0;
        key.type = BTRFS_ROOT_ITEM_KEY;
-       ret = btrfs_search_slot(NULL, root->fs_info->tree_root,
-                                       &key, &path, 0, 0);
+       ret = btrfs_search_slot(NULL, fs_info->tree_root, &key, &path, 0, 0);
        if (ret < 0)
                goto out;
        while(1) {
@@ -9947,17 +9949,15 @@ again:
                        last_snapshot = btrfs_root_last_snapshot(&ri);
                        if (btrfs_disk_key_objectid(&ri.drop_progress) == 0) {
                                level = btrfs_root_level(&ri);
-                               level_size = root->fs_info->nodesize;
                                ret = add_root_item_to_list(&normal_trees,
                                                found_key.objectid,
                                                btrfs_root_bytenr(&ri),
                                                last_snapshot, level,
-                                               0, level_size, NULL);
+                                               0, NULL);
                                if (ret < 0)
                                        goto out;
                        } else {
                                level = btrfs_root_level(&ri);
-                               level_size = root->fs_info->nodesize;
                                objectid = found_key.objectid;
                                btrfs_disk_key_to_cpu(&found_key,
                                                      &ri.drop_progress);
@@ -9965,8 +9965,7 @@ again:
                                                objectid,
                                                btrfs_root_bytenr(&ri),
                                                last_snapshot, level,
-                                               ri.drop_level,
-                                               level_size, &found_key);
+                                               ri.drop_level, &found_key);
                                if (ret < 0)
                                        goto out;
                        }
@@ -10021,12 +10020,12 @@ again:
 out:
        task_stop(ctx.info);
        if (repair) {
-               free_corrupt_blocks_tree(root->fs_info->corrupt_blocks);
+               free_corrupt_blocks_tree(fs_info->corrupt_blocks);
                extent_io_tree_cleanup(&excluded_extents);
-               root->fs_info->fsck_extent_cache = NULL;
-               root->fs_info->free_extent_hook = NULL;
-               root->fs_info->corrupt_blocks = NULL;
-               root->fs_info->excluded_extents = NULL;
+               fs_info->fsck_extent_cache = NULL;
+               fs_info->free_extent_hook = NULL;
+               fs_info->corrupt_blocks = NULL;
+               fs_info->excluded_extents = NULL;
        }
        free(bits);
        free_chunk_cache_tree(&chunk_cache);
@@ -10041,7 +10040,7 @@ out:
        free_root_item_list(&dropping_trees);
        return ret;
 loop:
-       free_corrupt_blocks_tree(root->fs_info->corrupt_blocks);
+       free_corrupt_blocks_tree(fs_info->corrupt_blocks);
        free_extent_cache_tree(&seen);
        free_extent_cache_tree(&pending);
        free_extent_cache_tree(&reada);
@@ -10441,7 +10440,7 @@ static int query_tree_block_level(struct btrfs_fs_info *fs_info, u64 bytenr)
        btrfs_release_path(&path);
 
        /* Get level from tree block as an alternative source */
-       eb = read_tree_block(fs_info, bytenr, fs_info->nodesize, transid);
+       eb = read_tree_block(fs_info, bytenr, transid);
        if (!extent_buffer_uptodate(eb)) {
                free_extent_buffer(eb);
                return -EIO;
@@ -10494,7 +10493,7 @@ static int check_tree_block_backref(struct btrfs_fs_info *fs_info, u64 root_id,
        }
 
        /* Read out the tree block to get item/node key */
-       eb = read_tree_block(fs_info, bytenr, root->fs_info->nodesize, 0);
+       eb = read_tree_block(fs_info, bytenr, 0);
        if (!extent_buffer_uptodate(eb)) {
                err |= REFERENCER_MISSING;
                free_extent_buffer(eb);
@@ -10595,7 +10594,7 @@ static int check_shared_block_backref(struct btrfs_fs_info *fs_info,
        int found_parent = 0;
        int i;
 
-       eb = read_tree_block(fs_info, parent, fs_info->nodesize, 0);
+       eb = read_tree_block(fs_info, parent, 0);
        if (!extent_buffer_uptodate(eb))
                goto out;
 
@@ -10748,7 +10747,7 @@ static int check_shared_data_backref(struct btrfs_fs_info *fs_info,
        int found_parent = 0;
        int i;
 
-       eb = read_tree_block(fs_info, parent, fs_info->nodesize, 0);
+       eb = read_tree_block(fs_info, parent, 0);
        if (!extent_buffer_uptodate(eb))
                goto out;
 
@@ -11467,11 +11466,6 @@ static int traverse_tree_block(struct btrfs_root *root,
                total_fs_tree_bytes += node->len;
        if (btrfs_header_owner(node) == BTRFS_EXTENT_TREE_OBJECTID)
                total_extent_tree_bytes += node->len;
-       if (!found_old_backref &&
-           btrfs_header_owner(node) == BTRFS_TREE_RELOC_OBJECTID &&
-           btrfs_header_backref_rev(node) == BTRFS_MIXED_BACKREF_REV &&
-           !btrfs_header_flag(node, BTRFS_HEADER_FLAG_RELOC))
-               found_old_backref = 1;
 
        /* pre-order tranversal, check itself first */
        level = btrfs_header_level(node);
@@ -11510,8 +11504,7 @@ static int traverse_tree_block(struct btrfs_root *root,
                 * As a btrfs tree has most 8 levels (0..7), so it's quite safe
                 * to call the function itself.
                 */
-               eb = read_tree_block(root->fs_info, blocknr,
-                               root->fs_info->nodesize, 0);
+               eb = read_tree_block(root->fs_info, blocknr, 0);
                if (extent_buffer_uptodate(eb)) {
                        ret = traverse_tree_block(root, eb);
                        err |= ret;
@@ -11525,15 +11518,18 @@ static int traverse_tree_block(struct btrfs_root *root,
 /*
  * Low memory usage version check_chunks_and_extents.
  */
-static int check_chunks_and_extents_v2(struct btrfs_root *root)
+static int check_chunks_and_extents_v2(struct btrfs_fs_info *fs_info)
 {
        struct btrfs_path path;
        struct btrfs_key key;
        struct btrfs_root *root1;
+       struct btrfs_root *root;
        struct btrfs_root *cur_root;
        int err = 0;
        int ret;
 
+       root = fs_info->fs_root;
+
        root1 = root->fs_info->chunk_root;
        ret = traverse_tree_block(root1, root1->node);
        err |= ret;
@@ -11585,6 +11581,20 @@ out:
        return err;
 }
 
+static int do_check_chunks_and_extents(struct btrfs_fs_info *fs_info)
+{
+       int ret;
+
+       if (!ctx.progress_enabled)
+               fprintf(stderr, "checking extents\n");
+       if (check_mode == CHECK_MODE_LOWMEM)
+               ret = check_chunks_and_extents_v2(fs_info);
+       else
+               ret = check_chunks_and_extents(fs_info);
+
+       return ret;
+}
+
 static int btrfs_fsck_reinit_root(struct btrfs_trans_handle *trans,
                           struct btrfs_root *root, int overwrite)
 {
@@ -11695,7 +11705,7 @@ static int pin_down_tree_blocks(struct btrfs_fs_info *fs_info,
                         * in, but for now this doesn't actually use the root so
                         * just pass in extent_root.
                         */
-                       tmp = read_tree_block(fs_info, bytenr, fs_info->nodesize, 0);
+                       tmp = read_tree_block(fs_info, bytenr, 0);
                        if (!extent_buffer_uptodate(tmp)) {
                                fprintf(stderr, "Error reading root block\n");
                                return -EIO;
@@ -11714,8 +11724,7 @@ static int pin_down_tree_blocks(struct btrfs_fs_info *fs_info,
                                continue;
                        }
 
-                       tmp = read_tree_block(fs_info, bytenr,
-                                             fs_info->nodesize, 0);
+                       tmp = read_tree_block(fs_info, bytenr, 0);
                        if (!extent_buffer_uptodate(tmp)) {
                                fprintf(stderr, "Error reading tree block\n");
                                return -EIO;
@@ -12672,6 +12681,45 @@ static int clear_free_space_cache(struct btrfs_fs_info *fs_info)
        return ret;
 }
 
+static int do_clear_free_space_cache(struct btrfs_fs_info *fs_info,
+               int clear_version)
+{
+       int ret = 0;
+
+       if (clear_version == 1) {
+               if (btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE)) {
+                       error(
+               "free space cache v2 detected, use --clear-space-cache v2");
+                       ret = 1;
+                       goto close_out;
+               }
+               printf("Clearing free space cache\n");
+               ret = clear_free_space_cache(fs_info);
+               if (ret) {
+                       error("failed to clear free space cache");
+                       ret = 1;
+               } else {
+                       printf("Free space cache cleared\n");
+               }
+       } else if (clear_version == 2) {
+               if (!btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE)) {
+                       printf("no free space cache v2 to clear\n");
+                       ret = 0;
+                       goto close_out;
+               }
+               printf("Clear free space cache v2\n");
+               ret = btrfs_clear_free_space_tree(fs_info);
+               if (ret) {
+                       error("failed to clear free space cache v2: %d", ret);
+                       ret = 1;
+               } else {
+                       printf("free space cache v2 cleared\n");
+               }
+       }
+close_out:
+       return ret;
+}
+
 const char * const cmd_check_usage[] = {
        "btrfs check [options] <device>",
        "Check structural integrity of a filesystem (unmounted).",
@@ -12682,6 +12730,7 @@ const char * const cmd_check_usage[] = {
        "",
        "-s|--super <superblock>     use this superblock copy",
        "-b|--backup                 use the first valid backup root copy",
+       "--force                     skip mount checks, repair is not possible",
        "--repair                    try to repair the filesystem",
        "--readonly                  run in read-only mode (default)",
        "--init-csum-tree            create a new CRC tree",
@@ -12713,7 +12762,7 @@ int cmd_check(int argc, char **argv)
        u64 tree_root_bytenr = 0;
        u64 chunk_root_bytenr = 0;
        char uuidbuf[BTRFS_UUID_UNPARSED_SIZE];
-       int ret;
+       int ret = 0;
        int err = 0;
        u64 num;
        int init_csum_tree = 0;
@@ -12722,13 +12771,15 @@ int cmd_check(int argc, char **argv)
        int qgroup_report = 0;
        int qgroups_repaired = 0;
        unsigned ctree_flags = OPEN_CTREE_EXCLUSIVE;
+       int force = 0;
 
        while(1) {
                int c;
                enum { GETOPT_VAL_REPAIR = 257, GETOPT_VAL_INIT_CSUM,
                        GETOPT_VAL_INIT_EXTENT, GETOPT_VAL_CHECK_CSUM,
                        GETOPT_VAL_READONLY, GETOPT_VAL_CHUNK_TREE,
-                       GETOPT_VAL_MODE, GETOPT_VAL_CLEAR_SPACE_CACHE };
+                       GETOPT_VAL_MODE, GETOPT_VAL_CLEAR_SPACE_CACHE,
+                       GETOPT_VAL_FORCE };
                static const struct option long_options[] = {
                        { "super", required_argument, NULL, 's' },
                        { "repair", no_argument, NULL, GETOPT_VAL_REPAIR },
@@ -12750,6 +12801,7 @@ int cmd_check(int argc, char **argv)
                                GETOPT_VAL_MODE },
                        { "clear-space-cache", required_argument, NULL,
                                GETOPT_VAL_CLEAR_SPACE_CACHE},
+                       { "force", no_argument, NULL, GETOPT_VAL_FORCE },
                        { NULL, 0, NULL, 0}
                };
 
@@ -12834,6 +12886,9 @@ int cmd_check(int argc, char **argv)
                                }
                                ctree_flags |= OPEN_CTREE_WRITES;
                                break;
+                       case GETOPT_VAL_FORCE:
+                               force = 1;
+                               break;
                }
        }
 
@@ -12862,15 +12917,36 @@ int cmd_check(int argc, char **argv)
        radix_tree_init();
        cache_tree_init(&root_cache);
 
-       if((ret = check_mounted(argv[optind])) < 0) {
-               error("could not check mount status: %s", strerror(-ret));
-               err |= !!ret;
-               goto err_out;
-       } else if(ret) {
-               error("%s is currently mounted, aborting", argv[optind]);
-               ret = -EBUSY;
-               err |= !!ret;
-               goto err_out;
+       ret = check_mounted(argv[optind]);
+       if (!force) {
+               if (ret < 0) {
+                       error("could not check mount status: %s",
+                                       strerror(-ret));
+                       err |= !!ret;
+                       goto err_out;
+               } else if (ret) {
+                       error(
+"%s is currently mounted, use --force if you really intend to check the filesystem",
+                               argv[optind]);
+                       ret = -EBUSY;
+                       err |= !!ret;
+                       goto err_out;
+               }
+       } else {
+               if (repair) {
+                       error("repair and --force is not yet supported");
+                       ret = 1;
+                       err |= !!ret;
+                       goto err_out;
+               }
+               if (ret < 0) {
+                       warning(
+"cannot check mount status of %s, the filesystem could be mounted, continuing because of --force",
+                               argv[optind]);
+               } else if (ret) {
+                       warning(
+                       "filesystem mounted, continuing because of --force");
+               }
        }
 
        /* only allow partial opening under repair mode */
@@ -12888,36 +12964,26 @@ int cmd_check(int argc, char **argv)
 
        global_info = info;
        root = info->fs_root;
-       if (clear_space_cache == 1) {
-               if (btrfs_fs_compat_ro(info, FREE_SPACE_TREE)) {
-                       error(
-               "free space cache v2 detected, use --clear-space-cache v2");
-                       ret = 1;
-                       goto close_out;
-               }
-               printf("Clearing free space cache\n");
-               ret = clear_free_space_cache(info);
-               if (ret) {
-                       error("failed to clear free space cache");
-                       ret = 1;
-               } else {
-                       printf("Free space cache cleared\n");
-               }
+       uuid_unparse(info->super_copy->fsid, uuidbuf);
+
+       printf("Checking filesystem on %s\nUUID: %s\n", argv[optind], uuidbuf);
+
+       /*
+        * Check the bare minimum before starting anything else that could rely
+        * on it, namely the tree roots, any local consistency checks
+        */
+       if (!extent_buffer_uptodate(info->tree_root->node) ||
+           !extent_buffer_uptodate(info->dev_root->node) ||
+           !extent_buffer_uptodate(info->chunk_root->node)) {
+               error("critical roots corrupted, unable to check the filesystem");
+               err |= !!ret;
+               ret = -EIO;
                goto close_out;
-       } else if (clear_space_cache == 2) {
-               if (!btrfs_fs_compat_ro(info, FREE_SPACE_TREE)) {
-                       printf("no free space cache v2 to clear\n");
-                       ret = 0;
-                       goto close_out;
-               }
-               printf("Clear free space cache v2\n");
-               ret = btrfs_clear_free_space_tree(info);
-               if (ret) {
-                       error("failed to clear free space cache v2: %d", ret);
-                       ret = 1;
-               } else {
-                       printf("free space cache v2 cleared\n");
-               }
+       }
+
+       if (clear_space_cache) {
+               ret = do_clear_free_space_cache(info, clear_space_cache);
+               err |= !!ret;
                goto close_out;
        }
 
@@ -12940,7 +13006,6 @@ int cmd_check(int argc, char **argv)
                }
        }
 
-       uuid_unparse(info->super_copy->fsid, uuidbuf);
        if (qgroup_report) {
                printf("Print quota groups for %s\nUUID: %s\n", argv[optind],
                       uuidbuf);
@@ -12957,16 +13022,6 @@ int cmd_check(int argc, char **argv)
                err |= !!ret;
                goto close_out;
        }
-       printf("Checking filesystem on %s\nUUID: %s\n", argv[optind], uuidbuf);
-
-       if (!extent_buffer_uptodate(info->tree_root->node) ||
-           !extent_buffer_uptodate(info->dev_root->node) ||
-           !extent_buffer_uptodate(info->chunk_root->node)) {
-               error("critical roots corrupted, unable to check the filesystem");
-               err |= !!ret;
-               ret = -EIO;
-               goto close_out;
-       }
 
        if (init_extent_tree || init_csum_tree) {
                struct btrfs_trans_handle *trans;
@@ -13028,12 +13083,7 @@ int cmd_check(int argc, char **argv)
                goto close_out;
        }
 
-       if (!ctx.progress_enabled)
-               fprintf(stderr, "checking extents\n");
-       if (check_mode == CHECK_MODE_LOWMEM)
-               ret = check_chunks_and_extents_v2(root);
-       else
-               ret = check_chunks_and_extents(root);
+       ret = do_check_chunks_and_extents(info);
        err |= !!ret;
        if (ret)
                error(
@@ -13082,12 +13132,7 @@ int cmd_check(int argc, char **argv)
         * ignore it when this happens.
         */
        no_holes = btrfs_fs_incompat(root->fs_info, NO_HOLES);
-       if (!ctx.progress_enabled)
-               fprintf(stderr, "checking fs roots\n");
-       if (check_mode == CHECK_MODE_LOWMEM)
-               ret = check_fs_roots_v2(root->fs_info);
-       else
-               ret = check_fs_roots(root, &root_cache);
+       ret = do_check_fs_roots(info, &root_cache);
        err |= !!ret;
        if (ret) {
                error("errors found in fs roots");
@@ -13163,17 +13208,6 @@ int cmd_check(int argc, char **argv)
                err |= !!ret;
        }
 out:
-       if (found_old_backref) { /*
-                * there was a disk format change when mixed
-                * backref was in testing tree. The old format
-                * existed about one week.
-                */
-               printf("\n * Found old mixed backref format. "
-                      "The old format is not supported! *"
-                      "\n * Please mount the FS in readonly mode, "
-                      "backup data and re-format the FS. *\n\n");
-               err |= 1;
-       }
        printf("found %llu bytes used, ",
               (unsigned long long)bytes_used);
        if (err)