int add_block_group_free_space(struct btrfs_trans_handle *trans, struct btrfs_fs_info *fs_info, struct btrfs_block_group_cache *block_group) { struct btrfs_path *path = NULL; int ret = 0; if (!btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE)) return 0; mutex_lock(&block_group->free_space_lock); if (!block_group->needs_free_space) goto out; path = btrfs_alloc_path(); if (!path) { ret = -ENOMEM; goto out; } ret = __add_block_group_free_space(trans, fs_info, block_group, path); out: btrfs_free_path(path); mutex_unlock(&block_group->free_space_lock); if (ret) btrfs_abort_transaction(trans, ret); return ret; }
int remove_from_free_space_tree(struct btrfs_trans_handle *trans, u64 start, u64 size) { struct btrfs_block_group_cache *block_group; struct btrfs_path *path; int ret; if (!btrfs_fs_compat_ro(trans->fs_info, FREE_SPACE_TREE)) return 0; path = btrfs_alloc_path(); if (!path) { ret = -ENOMEM; goto out; } block_group = btrfs_lookup_block_group(trans->fs_info, start); if (!block_group) { ASSERT(0); ret = -ENOENT; goto out; } mutex_lock(&block_group->free_space_lock); ret = __remove_from_free_space_tree(trans, block_group, path, start, size); mutex_unlock(&block_group->free_space_lock); btrfs_put_block_group(block_group); out: btrfs_free_path(path); if (ret) btrfs_abort_transaction(trans, ret); return ret; }
int remove_block_group_free_space(struct btrfs_trans_handle *trans, struct btrfs_fs_info *fs_info, struct btrfs_block_group_cache *block_group) { struct btrfs_root *root = fs_info->free_space_root; struct btrfs_path *path; struct btrfs_key key, found_key; struct extent_buffer *leaf; u64 start, end; int done = 0, nr; int ret; if (!btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE)) return 0; if (block_group->needs_free_space) { /* We never added this block group to the free space tree. */ return 0; } path = btrfs_alloc_path(); if (!path) { ret = -ENOMEM; goto out; } start = block_group->key.objectid; end = block_group->key.objectid + block_group->key.offset; key.objectid = end - 1; key.type = (u8)-1; key.offset = (u64)-1; while (!done) { ret = btrfs_search_prev_slot(trans, root, &key, path, -1, 1); if (ret) goto out; leaf = path->nodes[0]; nr = 0; path->slots[0]++; while (path->slots[0] > 0) { btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0] - 1); if (found_key.type == BTRFS_FREE_SPACE_INFO_KEY) { ASSERT(found_key.objectid == block_group->key.objectid); ASSERT(found_key.offset == block_group->key.offset); done = 1; nr++; path->slots[0]--; break; } else if (found_key.type == BTRFS_FREE_SPACE_EXTENT_KEY || found_key.type == BTRFS_FREE_SPACE_BITMAP_KEY) { ASSERT(found_key.objectid >= start); ASSERT(found_key.objectid < end); ASSERT(found_key.objectid + found_key.offset <= end); nr++; path->slots[0]--; } else { ASSERT(0); } } ret = btrfs_del_items(trans, root, path, path->slots[0], nr); if (ret) goto out; btrfs_release_path(path); } ret = 0; out: btrfs_free_path(path); if (ret) btrfs_abort_transaction(trans, ret); return ret; }