btrfs-progs: Add new option for specify chunk root bytenr
[platform/upstream/btrfs-progs.git] / cmds-check.c
index cb48b79..0a48535 100644 (file)
@@ -35,6 +35,7 @@
 #include "utils.h"
 #include "commands.h"
 #include "free-space-cache.h"
+#include "free-space-tree.h"
 #include "btrfsck.h"
 #include "qgroup-verify.h"
 #include "rbtree-utils.h"
@@ -952,6 +953,8 @@ static struct inode_backref *get_inode_backref(struct inode_record *rec,
        }
 
        backref = malloc(sizeof(*backref) + namelen + 1);
+       if (!backref)
+               return NULL;
        memset(backref, 0, sizeof(*backref));
        backref->dir = dir;
        backref->namelen = namelen;
@@ -972,6 +975,7 @@ static int add_inode_backref(struct cache_tree *inode_cache,
        rec = get_inode_rec(inode_cache, ino, 1);
        BUG_ON(IS_ERR(rec));
        backref = get_inode_backref(rec, name, namelen, dir);
+       BUG_ON(!backref);
        if (errors)
                backref->errors |= errors;
        if (itemtype == BTRFS_DIR_INDEX_KEY) {
@@ -1125,6 +1129,7 @@ again:
                        ins = node;
                } else {
                        ins = malloc(sizeof(*ins));
+                       BUG_ON(!ins);
                        ins->cache.start = node->cache.start;
                        ins->cache.size = node->cache.size;
                        ins->data = rec;
@@ -4350,6 +4355,9 @@ static struct tree_backref *alloc_tree_backref(struct extent_record *rec,
                                                u64 parent, u64 root)
 {
        struct tree_backref *ref = malloc(sizeof(*ref));
+
+       if (!ref)
+               return NULL;
        memset(&ref->node, 0, sizeof(ref->node));
        if (parent > 0) {
                ref->parent = parent;
@@ -4406,6 +4414,9 @@ static struct data_backref *alloc_data_backref(struct extent_record *rec,
                                                u64 max_size)
 {
        struct data_backref *ref = malloc(sizeof(*ref));
+
+       if (!ref)
+               return NULL;
        memset(&ref->node, 0, sizeof(ref->node));
        ref->node.is_data = 1;
 
@@ -4576,6 +4587,8 @@ static int add_extent_rec(struct cache_tree *extent_cache,
                return ret;
        }
        rec = malloc(sizeof(*rec));
+       if (!rec)
+               return -ENOMEM;
        rec->start = start;
        rec->max_size = max_size;
        rec->nr = max(nr, max_size);
@@ -4656,8 +4669,10 @@ static int add_tree_backref(struct cache_tree *extent_cache, u64 bytenr,
        }
 
        back = find_tree_backref(rec, parent, root);
-       if (!back)
+       if (!back) {
                back = alloc_tree_backref(rec, parent, root);
+               BUG_ON(!back);
+       }
 
        if (found_ref) {
                if (back->node.found_ref) {
@@ -4716,9 +4731,11 @@ static int add_data_backref(struct cache_tree *extent_cache, u64 bytenr,
         */
        back = find_data_backref(rec, parent, root, owner, offset, found_ref,
                                 bytenr, max_size);
-       if (!back)
+       if (!back) {
                back = alloc_data_backref(rec, parent, root, owner, offset,
                                          max_size);
+               BUG_ON(!back);
+       }
 
        if (found_ref) {
                BUG_ON(num_refs != 1);
@@ -5460,9 +5477,29 @@ static int check_space_cache(struct btrfs_root *root)
                        btrfs_remove_free_space_cache(cache);
                }
 
-               ret = load_free_space_cache(root->fs_info, cache);
-               if (!ret)
-                       continue;
+               if (btrfs_fs_compat_ro(root->fs_info,
+                                      BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE)) {
+                       ret = exclude_super_stripes(root, cache);
+                       if (ret) {
+                               fprintf(stderr, "could not exclude super stripes: %s\n",
+                                       strerror(-ret));
+                               error++;
+                               continue;
+                       }
+                       ret = load_free_space_tree(root->fs_info, cache);
+                       free_excluded_extents(root, cache);
+                       if (ret < 0) {
+                               fprintf(stderr, "could not load free space tree: %s\n",
+                                       strerror(-ret));
+                               error++;
+                               continue;
+                       }
+                       error += ret;
+               } else {
+                       ret = load_free_space_cache(root->fs_info, cache);
+                       if (!ret)
+                               continue;
+               }
 
                ret = verify_space_cache(root, cache);
                if (ret) {
@@ -9181,11 +9218,11 @@ static int build_roots_info_cache(struct btrfs_fs_info *info)
                        iref = (struct btrfs_extent_inline_ref *)(ei + 1);
                        level = found_key.offset;
                } else {
-                       struct btrfs_tree_block_info *info;
+                       struct btrfs_tree_block_info *binfo;
 
-                       info = (struct btrfs_tree_block_info *)(ei + 1);
-                       iref = (struct btrfs_extent_inline_ref *)(info + 1);
-                       level = btrfs_tree_block_level(leaf, info);
+                       binfo = (struct btrfs_tree_block_info *)(ei + 1);
+                       iref = (struct btrfs_extent_inline_ref *)(binfo + 1);
+                       level = btrfs_tree_block_level(leaf, binfo);
                }
 
                /*
@@ -9443,6 +9480,7 @@ const char * const cmd_check_usage[] = {
        "-E|--subvol-extents <subvolid>",
        "                            print subvolume extents and sharing state",
        "-r|--tree-root <bytenr>     use the given bytenr for the tree root",
+       "-c|--chunk-root <bytenr>    use the given bytenr for the chunk tree root",
        "-p|--progress               indicate progress",
        NULL
 };
@@ -9455,6 +9493,7 @@ int cmd_check(int argc, char **argv)
        u64 bytenr = 0;
        u64 subvolid = 0;
        u64 tree_root_bytenr = 0;
+       u64 chunk_root_bytenr = 0;
        char uuidbuf[BTRFS_UUID_UNPARSED_SIZE];
        int ret;
        u64 num;
@@ -9478,11 +9517,12 @@ int cmd_check(int argc, char **argv)
                        { "subvol-extents", required_argument, NULL, 'E' },
                        { "qgroup-report", no_argument, NULL, 'Q' },
                        { "tree-root", required_argument, NULL, 'r' },
+                       { "chunk-root", required_argument, NULL, 'c' },
                        { "progress", no_argument, NULL, 'p' },
                        { NULL, 0, NULL, 0}
                };
 
-               c = getopt_long(argc, argv, "as:br:p", long_options, NULL);
+               c = getopt_long(argc, argv, "as:br:pc:", long_options, NULL);
                if (c < 0)
                        break;
                switch(c) {
@@ -9511,6 +9551,9 @@ int cmd_check(int argc, char **argv)
                        case 'r':
                                tree_root_bytenr = arg_strtou64(optarg);
                                break;
+                       case 'c':
+                               chunk_root_bytenr = arg_strtou64(optarg);
+                               break;
                        case 'p':
                                ctx.progress_enabled = true;
                                break;
@@ -9542,9 +9585,8 @@ int cmd_check(int argc, char **argv)
                                break;
                }
        }
-       argc = argc - optind;
 
-       if (check_argc_exact(argc, 1))
+       if (check_argc_exact(argc - optind, 1))
                usage(cmd_check_usage);
 
        if (ctx.progress_enabled) {
@@ -9575,7 +9617,7 @@ int cmd_check(int argc, char **argv)
                ctree_flags |= OPEN_CTREE_PARTIAL;
 
        info = open_ctree_fs_info(argv[optind], bytenr, tree_root_bytenr,
-                                 ctree_flags);
+                                 chunk_root_bytenr, ctree_flags);
        if (!info) {
                fprintf(stderr, "Couldn't open file system\n");
                ret = -EIO;
@@ -9701,8 +9743,12 @@ int cmd_check(int argc, char **argv)
                goto close_out;
        }
 
-       if (!ctx.progress_enabled)
-               fprintf(stderr, "checking free space cache\n");
+       if (!ctx.progress_enabled) {
+               if (btrfs_fs_compat_ro(info, BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE))
+                       fprintf(stderr, "checking free space tree\n");
+               else
+                       fprintf(stderr, "checking free space cache\n");
+       }
        ret = check_space_cache(root);
        if (ret)
                goto out;