if (!cache) {
printk("Unable to find block group for %llu\n",
(unsigned long long)search_start);
- WARN_ON(1);
+ return -ENOENT;
}
return -ENOSPC;
extra_size = -1;
if (owner < BTRFS_FIRST_FREE_OBJECTID && skinny_metadata) {
- skinny_metadata = 1;
key.type = BTRFS_METADATA_ITEM_KEY;
key.offset = owner;
} else if (skinny_metadata) {
printf("Size is %u, needs to be %u, slot %d\n",
(unsigned)item_size,
(unsigned)sizeof(*ei), path->slots[0]);
- btrfs_print_leaf(root, leaf);
+ btrfs_print_leaf(leaf);
return -EINVAL;
}
BUG_ON(item_size < sizeof(*ei));
}
if (ret != 0) {
- btrfs_print_leaf(root, path->nodes[0]);
+ btrfs_print_leaf(path->nodes[0]);
printk("failed to find block number %Lu\n",
(unsigned long long)bytenr);
BUG();
}
static int do_chunk_alloc(struct btrfs_trans_handle *trans,
- struct btrfs_root *extent_root, u64 alloc_bytes,
+ struct btrfs_fs_info *fs_info, u64 alloc_bytes,
u64 flags)
{
struct btrfs_space_info *space_info;
u64 num_bytes;
int ret;
- space_info = __find_space_info(extent_root->fs_info, flags);
+ space_info = __find_space_info(fs_info, flags);
if (!space_info) {
- ret = update_space_info(extent_root->fs_info, flags,
- 0, 0, &space_info);
+ ret = update_space_info(fs_info, flags, 0, 0, &space_info);
BUG_ON(ret);
}
BUG_ON(!space_info);
/*
* Avoid allocating given chunk type
*/
- if (extent_root->fs_info->avoid_meta_chunk_alloc &&
+ if (fs_info->avoid_meta_chunk_alloc &&
(flags & BTRFS_BLOCK_GROUP_METADATA))
return 0;
- if (extent_root->fs_info->avoid_sys_chunk_alloc &&
+ if (fs_info->avoid_sys_chunk_alloc &&
(flags & BTRFS_BLOCK_GROUP_SYSTEM))
return 0;
- ret = btrfs_alloc_chunk(trans, extent_root, &start, &num_bytes,
+ ret = btrfs_alloc_chunk(trans, fs_info, &start, &num_bytes,
space_info->flags);
if (ret == -ENOSPC) {
space_info->full = 1;
BUG_ON(ret);
- ret = btrfs_make_block_group(trans, extent_root, 0, space_info->flags,
- BTRFS_FIRST_CHUNK_TREE_OBJECTID, start, num_bytes);
+ ret = btrfs_make_block_group(trans, fs_info, 0, space_info->flags,
+ start, num_bytes);
BUG_ON(ret);
return 0;
}
-static int update_block_group(struct btrfs_trans_handle *trans,
- struct btrfs_root *root,
+static int update_block_group(struct btrfs_root *root,
u64 bytenr, u64 num_bytes, int alloc,
int mark_free)
{
printk(KERN_ERR "umm, got %d back from search"
", was looking for %llu\n", ret,
(unsigned long long)bytenr);
- btrfs_print_leaf(extent_root, path->nodes[0]);
+ btrfs_print_leaf(path->nodes[0]);
}
BUG_ON(ret);
extent_slot = path->slots[0];
printk(KERN_ERR "umm, got %d back from search"
", was looking for %llu\n", ret,
(unsigned long long)bytenr);
- btrfs_print_leaf(extent_root, path->nodes[0]);
+ btrfs_print_leaf(path->nodes[0]);
}
BUG_ON(ret);
extent_slot = path->slots[0];
BUG_ON(ret);
}
- update_block_group(trans, root, bytenr, num_bytes, 0, mark_free);
+ update_block_group(root, bytenr, num_bytes, 0, mark_free);
}
fail:
btrfs_free_path(path);
goto no_bg_cache;
bg_offset = ins->objectid - bg_cache->key.objectid;
- search_start = round_up(bg_offset + num_bytes,
- BTRFS_STRIPE_LEN) + bg_offset;
+ search_start = round_up(
+ bg_offset + num_bytes, BTRFS_STRIPE_LEN) +
+ bg_cache->key.objectid;
goto new_group;
}
no_bg_cache:
struct btrfs_root *root,
u64 num_bytes, u64 empty_size,
u64 hint_byte, u64 search_end,
- struct btrfs_key *ins, int data)
+ struct btrfs_key *ins, bool is_data)
{
int ret;
u64 search_start = 0;
u64 alloc_profile;
+ u64 profile;
struct btrfs_fs_info *info = root->fs_info;
- if (data) {
+ if (is_data) {
alloc_profile = info->avail_data_alloc_bits &
info->data_alloc_profile;
- data = BTRFS_BLOCK_GROUP_DATA | alloc_profile;
- } else if ((info->system_allocs > 0 || root == info->chunk_root) &&
- info->system_allocs >= 0) {
+ profile = BTRFS_BLOCK_GROUP_DATA | alloc_profile;
+ } else if (info->system_allocs == 1 || root == info->chunk_root) {
alloc_profile = info->avail_system_alloc_bits &
info->system_alloc_profile;
- data = BTRFS_BLOCK_GROUP_SYSTEM | alloc_profile;
+ profile = BTRFS_BLOCK_GROUP_SYSTEM | alloc_profile;
} else {
alloc_profile = info->avail_metadata_alloc_bits &
info->metadata_alloc_profile;
- data = BTRFS_BLOCK_GROUP_METADATA | alloc_profile;
+ profile = BTRFS_BLOCK_GROUP_METADATA | alloc_profile;
}
if (root->ref_cows) {
- if (!(data & BTRFS_BLOCK_GROUP_METADATA)) {
- ret = do_chunk_alloc(trans, root->fs_info->extent_root,
+ if (!(profile & BTRFS_BLOCK_GROUP_METADATA)) {
+ ret = do_chunk_alloc(trans, info,
num_bytes,
BTRFS_BLOCK_GROUP_METADATA);
BUG_ON(ret);
}
- ret = do_chunk_alloc(trans, root->fs_info->extent_root,
- num_bytes + SZ_2M, data);
+ ret = do_chunk_alloc(trans, info,
+ num_bytes + SZ_2M, profile);
BUG_ON(ret);
}
ret = find_free_extent(trans, root, num_bytes, empty_size,
search_start, search_end, hint_byte, ins,
trans->alloc_exclude_start,
- trans->alloc_exclude_nr, data);
- BUG_ON(ret);
- clear_extent_dirty(&root->fs_info->free_space_cache,
+ trans->alloc_exclude_nr, profile);
+ if (ret < 0)
+ return ret;
+ clear_extent_dirty(&info->free_space_cache,
ins->objectid, ins->objectid + ins->offset - 1);
return ret;
}
btrfs_mark_buffer_dirty(leaf);
btrfs_free_path(path);
- ret = update_block_group(trans, root, ins->objectid, fs_info->nodesize,
+ ret = update_block_group(root, ins->objectid, fs_info->nodesize,
1, 0);
return ret;
}
return ERR_PTR(ret);
}
- buf = btrfs_find_create_tree_block(root->fs_info, ins.objectid,
- blocksize);
+ buf = btrfs_find_create_tree_block(root->fs_info, ins.objectid);
if (!buf) {
btrfs_free_extent(trans, root, ins.objectid, ins.offset,
0, root->root_key.objectid, level, 0);
bit = BLOCK_GROUP_METADATA;
}
set_avail_alloc_bits(info, cache->flags);
- if (btrfs_chunk_readonly(root, cache->key.objectid))
+ if (btrfs_chunk_readonly(info, cache->key.objectid))
cache->ro = 1;
account_super_bytes(info, cache);
struct btrfs_block_group_cache *
btrfs_add_block_group(struct btrfs_fs_info *fs_info, u64 bytes_used, u64 type,
- u64 chunk_objectid, u64 chunk_offset, u64 size)
+ u64 chunk_offset, u64 size)
{
int ret;
int bit = 0;
cache->key.type = BTRFS_BLOCK_GROUP_ITEM_KEY;
btrfs_set_block_group_used(&cache->item, bytes_used);
- btrfs_set_block_group_chunk_objectid(&cache->item, chunk_objectid);
+ btrfs_set_block_group_chunk_objectid(&cache->item,
+ BTRFS_FIRST_CHUNK_TREE_OBJECTID);
cache->flags = type;
btrfs_set_block_group_flags(&cache->item, type);
}
int btrfs_make_block_group(struct btrfs_trans_handle *trans,
- struct btrfs_root *root, u64 bytes_used,
- u64 type, u64 chunk_objectid, u64 chunk_offset,
- u64 size)
+ struct btrfs_fs_info *fs_info, u64 bytes_used,
+ u64 type, u64 chunk_offset, u64 size)
{
int ret;
- struct btrfs_root *extent_root;
+ struct btrfs_root *extent_root = fs_info->extent_root;
struct btrfs_block_group_cache *cache;
- cache = btrfs_add_block_group(root->fs_info, bytes_used, type,
- chunk_objectid, chunk_offset, size);
- extent_root = root->fs_info->extent_root;
+ cache = btrfs_add_block_group(fs_info, bytes_used, type, chunk_offset,
+ size);
ret = btrfs_insert_item(trans, extent_root, &cache->key, &cache->item,
sizeof(cache->item));
BUG_ON(ret);
* before doing any block allocation.
*/
int btrfs_make_block_groups(struct btrfs_trans_handle *trans,
- struct btrfs_root *root)
+ struct btrfs_fs_info *fs_info)
{
u64 total_bytes;
u64 cur_start;
u64 chunk_objectid;
int ret;
int bit;
- struct btrfs_root *extent_root;
+ struct btrfs_root *extent_root = fs_info->extent_root;
struct btrfs_block_group_cache *cache;
struct extent_io_tree *block_group_cache;
- extent_root = root->fs_info->extent_root;
- block_group_cache = &root->fs_info->block_group_cache;
+ block_group_cache = &fs_info->block_group_cache;
chunk_objectid = BTRFS_FIRST_CHUNK_TREE_OBJECTID;
- total_bytes = btrfs_super_total_bytes(root->fs_info->super_copy);
- group_align = 64 * root->fs_info->sectorsize;
+ total_bytes = btrfs_super_total_bytes(fs_info->super_copy);
+ group_align = 64 * fs_info->sectorsize;
cur_start = 0;
while (cur_start < total_bytes) {
cache->flags = group_type;
- ret = update_space_info(root->fs_info, group_type, group_size,
+ ret = update_space_info(fs_info, group_type, group_size,
0, &cache->space_info);
BUG_ON(ret);
- set_avail_alloc_bits(extent_root->fs_info, group_type);
+ set_avail_alloc_bits(fs_info, group_type);
set_extent_bits(block_group_cache, cur_start,
cur_start + group_size - 1,
/* then insert all the items */
cur_start = 0;
while(cur_start < total_bytes) {
- cache = btrfs_lookup_block_group(root->fs_info, cur_start);
+ cache = btrfs_lookup_block_group(fs_info, cur_start);
BUG_ON(!cache);
ret = btrfs_insert_item(trans, extent_root, &cache->key, &cache->item,
return 0;
}
-int btrfs_update_block_group(struct btrfs_trans_handle *trans,
- struct btrfs_root *root,
+int btrfs_update_block_group(struct btrfs_root *root,
u64 bytenr, u64 num_bytes, int alloc,
int mark_free)
{
- return update_block_group(trans, root, bytenr, num_bytes,
+ return update_block_group(root, bytenr, num_bytes,
alloc, mark_free);
}
btrfs_remove_free_space_cache(cache);
kfree(cache->free_space_ctl);
}
- clear_extent_bits(&fs_info->block_group_cache, bytenr, bytenr + len,
+ clear_extent_bits(&fs_info->block_group_cache, bytenr, bytenr + len - 1,
(unsigned int)-1);
ret = free_space_info(fs_info, flags, len, 0, NULL);
if (ret < 0)
int btrfs_fix_block_accounting(struct btrfs_trans_handle *trans,
struct btrfs_root *root)
{
- int ret;
+ int ret = 0;
int slot;
u64 start = 0;
u64 bytes_used = 0;
btrfs_item_key_to_cpu(leaf, &key, slot);
if (key.type == BTRFS_EXTENT_ITEM_KEY) {
bytes_used += key.offset;
- ret = btrfs_update_block_group(trans, root,
+ ret = btrfs_update_block_group(root,
key.objectid, key.offset, 1, 0);
BUG_ON(ret);
} else if (key.type == BTRFS_METADATA_ITEM_KEY) {
bytes_used += fs_info->nodesize;
- ret = btrfs_update_block_group(trans, root,
+ ret = btrfs_update_block_group(root,
key.objectid, fs_info->nodesize, 1, 0);
- BUG_ON(ret);
+ if (ret)
+ goto out;
}
path.slots[0]++;
}
btrfs_set_super_bytes_used(root->fs_info->super_copy, bytes_used);
+ ret = 0;
+out:
btrfs_release_path(&path);
- return 0;
+ return ret;
}
static void __get_extent_size(struct btrfs_root *root, struct btrfs_path *path,
BTRFS_EXTENT_FLAG_DATA);
btrfs_mark_buffer_dirty(leaf);
- ret = btrfs_update_block_group(trans, root, disk_bytenr,
+ ret = btrfs_update_block_group(root, disk_bytenr,
num_bytes, 1, 0);
if (ret)
goto fail;