#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"
}
backref = malloc(sizeof(*backref) + namelen + 1);
+ if (!backref)
+ return NULL;
memset(backref, 0, sizeof(*backref));
backref->dir = dir;
backref->namelen = namelen;
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) {
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;
struct shared_node *node;
node = calloc(1, sizeof(*node));
+ if (!node)
+ return -ENOMEM;
node->cache.start = bytenr;
node->cache.size = 1;
cache_tree_init(&node->root_cache);
node->refs = refs;
ret = insert_cache_extent(shared, &node->cache);
- BUG_ON(ret);
- return 0;
+
+ return ret;
}
static int enter_shared_node(struct btrfs_root *root, u64 bytenr, u32 refs,
{
struct shared_node *node;
struct shared_node *dest;
+ int ret;
if (level == wc->active_node)
return 0;
BUG_ON(wc->active_node <= level);
node = find_shared_node(&wc->shared, bytenr);
if (!node) {
- add_shared_node(&wc->shared, bytenr, refs);
+ ret = add_shared_node(&wc->shared, bytenr, refs);
+ BUG_ON(ret);
node = find_shared_node(&wc->shared, bytenr);
wc->nodes[level] = node;
wc->active_node = level;
rec = container_of(cache, struct root_record, cache);
} else {
rec = calloc(1, sizeof(*rec));
+ if (!rec)
+ return ERR_PTR(-ENOMEM);
rec->objectid = objectid;
INIT_LIST_HEAD(&rec->backrefs);
rec->cache.start = objectid;
rec->cache.size = 1;
ret = insert_cache_extent(root_cache, &rec->cache);
- BUG_ON(ret);
+ if (ret)
+ return ERR_PTR(-EEXIST);
}
return rec;
}
}
backref = calloc(1, sizeof(*backref) + namelen + 1);
+ if (!backref)
+ return NULL;
backref->ref_root = ref_root;
backref->dir = dir;
backref->index = index;
struct root_backref *backref;
rec = get_root_rec(root_cache, root_id);
+ BUG_ON(IS_ERR(rec));
backref = get_root_backref(rec, ref_root, dir, index, name, namelen);
+ BUG_ON(!backref);
backref->errors |= errors;
int errors = 0;
rec = get_root_rec(root_cache, BTRFS_FS_TREE_OBJECTID);
+ BUG_ON(IS_ERR(rec));
rec->found_ref = 1;
/* fixme: this can not detect circular references */
ref_root = get_root_rec(root_cache,
backref->ref_root);
+ BUG_ON(IS_ERR(ref_root));
if (ref_root->found_ref > 0)
continue;
if (root->root_key.objectid != BTRFS_TREE_RELOC_OBJECTID) {
rec = get_root_rec(root_cache, root->root_key.objectid);
+ BUG_ON(IS_ERR(rec));
if (btrfs_root_refs(root_item) > 0)
rec->found_root_item = 1;
}
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;
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;
return ret;
}
rec = malloc(sizeof(*rec));
+ if (!rec)
+ return -ENOMEM;
rec->start = start;
rec->max_size = max_size;
rec->nr = max(nr, max_size);
}
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) {
*/
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);
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) {
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);
}
/*
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;