Loading fs/btrfs/ctree.h +7 −9 Original line number Diff line number Diff line Loading @@ -283,10 +283,6 @@ struct btrfs_block_group_item { struct btrfs_block_group_cache { struct btrfs_key key; struct btrfs_block_group_item item; u64 first_free; u64 last_alloc; u64 pinned; u64 last_prealloc; int data; int cached; }; Loading @@ -296,11 +292,13 @@ struct btrfs_fs_info { struct btrfs_root *extent_root; struct btrfs_root *tree_root; struct radix_tree_root fs_roots_radix; struct radix_tree_root pending_del_radix; struct radix_tree_root pinned_radix; struct radix_tree_root extent_ins_radix; struct extent_map_tree free_space_cache; struct extent_map_tree block_group_cache; struct extent_map_tree pinned_extents; struct extent_map_tree pending_del; struct extent_map_tree extent_ins; u64 generation; u64 last_trans_committed; struct btrfs_transaction *running_transaction; Loading Loading @@ -926,7 +924,7 @@ static inline int btrfs_set_root_name(struct btrfs_root *root, /* extent-tree.c */ int btrfs_extent_post_op(struct btrfs_trans_handle *trans, struct btrfs_root *root); int btrfs_copy_pinned(struct btrfs_root *root, struct radix_tree_root *copy); int btrfs_copy_pinned(struct btrfs_root *root, struct extent_map_tree *copy); struct btrfs_block_group_cache *btrfs_lookup_block_group(struct btrfs_fs_info *info, u64 blocknr); Loading @@ -949,7 +947,7 @@ int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root *root, u64 blocknr, u64 num_blocks, int pin); int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct radix_tree_root *unpin_radix); struct extent_map_tree *unpin); int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, u64 blocknr, u64 num_blocks); Loading fs/btrfs/disk-io.c +6 −3 Original line number Diff line number Diff line Loading @@ -432,9 +432,6 @@ struct btrfs_root *open_ctree(struct super_block *sb) err = -ENOMEM; goto fail; } init_bit_radix(&fs_info->pinned_radix); init_bit_radix(&fs_info->pending_del_radix); init_bit_radix(&fs_info->extent_ins_radix); INIT_RADIX_TREE(&fs_info->fs_roots_radix, GFP_NOFS); INIT_LIST_HEAD(&fs_info->trans_list); INIT_LIST_HEAD(&fs_info->dead_roots); Loading @@ -458,6 +455,12 @@ struct btrfs_root *open_ctree(struct super_block *sb) fs_info->btree_inode->i_mapping, GFP_NOFS); extent_map_tree_init(&fs_info->block_group_cache, fs_info->btree_inode->i_mapping, GFP_NOFS); extent_map_tree_init(&fs_info->pinned_extents, fs_info->btree_inode->i_mapping, GFP_NOFS); extent_map_tree_init(&fs_info->pending_del, fs_info->btree_inode->i_mapping, GFP_NOFS); extent_map_tree_init(&fs_info->extent_ins, fs_info->btree_inode->i_mapping, GFP_NOFS); fs_info->do_barriers = 1; fs_info->closing = 0; Loading fs/btrfs/extent-tree.c +72 −121 Original line number Diff line number Diff line Loading @@ -188,13 +188,13 @@ static u64 find_search_start(struct btrfs_root *root, return start; } out: return max(cache->last_alloc, search_start); return search_start; new_group: cache = btrfs_lookup_block_group(root->fs_info, last + cache->key.offset - 1); if (!cache) { return max((*cache_ret)->last_alloc, search_start); return search_start; } cache = btrfs_find_block_group(root, cache, last + cache->key.offset - 1, data, 0); Loading Loading @@ -247,16 +247,14 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root, shint = btrfs_lookup_block_group(info, search_start); if (shint && shint->data == data) { used = btrfs_block_group_used(&shint->item); if (used + shint->pinned < div_factor(shint->key.offset, factor)) { if (used < div_factor(shint->key.offset, factor)) { return shint; } } } if (hint && hint->data == data) { used = btrfs_block_group_used(&hint->item); if (used + hint->pinned < div_factor(hint->key.offset, factor)) { if (used < div_factor(hint->key.offset, factor)) { return hint; } last = hint->key.offset * 3; Loading Loading @@ -294,7 +292,7 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root, else free_check = div_factor(cache->key.offset, factor); if (used + cache->pinned < free_check) { if (used < free_check) { found_group = cache; goto found; } Loading Loading @@ -505,8 +503,6 @@ static int write_one_cache_group(struct btrfs_trans_handle *trans, return ret; if (pending_ret) return pending_ret; if (cache->data) cache->last_alloc = cache->first_free; return 0; } Loading Loading @@ -588,8 +584,6 @@ static int update_block_group(struct btrfs_trans_handle *trans, old_val = btrfs_block_group_used(&cache->item); num = min(total, cache->key.offset - block_in_group); if (alloc) { if (blocknr > cache->last_alloc) cache->last_alloc = blocknr; if (cache->data != data && old_val < (cache->key.offset >> 1)) { int bit_to_clear; Loading Loading @@ -617,8 +611,6 @@ static int update_block_group(struct btrfs_trans_handle *trans, old_val += num; } else { old_val -= num; if (blocknr < cache->first_free) cache->first_free = blocknr; if (mark_free) { set_extent_dirty(&info->free_space_cache, blocknr, blocknr + num - 1, Loading @@ -632,65 +624,47 @@ static int update_block_group(struct btrfs_trans_handle *trans, return 0; } int btrfs_copy_pinned(struct btrfs_root *root, struct radix_tree_root *copy) int btrfs_copy_pinned(struct btrfs_root *root, struct extent_map_tree *copy) { unsigned long gang[8]; u64 last = 0; struct radix_tree_root *pinned_radix = &root->fs_info->pinned_radix; u64 start; u64 end; struct extent_map_tree *pinned_extents = &root->fs_info->pinned_extents; int ret; int i; while(1) { ret = find_first_radix_bit(pinned_radix, gang, last, ARRAY_SIZE(gang)); if (!ret) ret = find_first_extent_bit(pinned_extents, last, &start, &end, EXTENT_DIRTY); if (ret) break; for (i = 0 ; i < ret; i++) { set_radix_bit(copy, gang[i]); last = gang[i] + 1; } set_extent_dirty(copy, start, end, GFP_NOFS); last = end + 1; } ret = find_first_radix_bit(&root->fs_info->extent_ins_radix, gang, 0, ARRAY_SIZE(gang)); WARN_ON(ret); return 0; } int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct radix_tree_root *unpin_radix) struct extent_map_tree *unpin) { unsigned long gang[8]; struct btrfs_block_group_cache *block_group; u64 first = 0; u64 start; u64 end; int ret; int i; struct radix_tree_root *pinned_radix = &root->fs_info->pinned_radix; struct extent_map_tree *pinned_extents = &root->fs_info->pinned_extents; struct extent_map_tree *free_space_cache; free_space_cache = &root->fs_info->free_space_cache; while(1) { ret = find_first_radix_bit(unpin_radix, gang, 0, ARRAY_SIZE(gang)); if (!ret) ret = find_first_extent_bit(unpin, 0, &start, &end, EXTENT_DIRTY); if (ret) break; if (!first) first = gang[0]; for (i = 0; i < ret; i++) { clear_radix_bit(pinned_radix, gang[i]); clear_radix_bit(unpin_radix, gang[i]); block_group = btrfs_lookup_block_group(root->fs_info, gang[i]); if (block_group) { WARN_ON(block_group->pinned == 0); block_group->pinned--; if (gang[i] < block_group->last_alloc) block_group->last_alloc = gang[i]; set_extent_dirty(free_space_cache, gang[i], gang[i], GFP_NOFS); } } clear_extent_dirty(pinned_extents, start, end, GFP_NOFS); clear_extent_dirty(unpin, start, end, GFP_NOFS); set_extent_dirty(free_space_cache, start, end, GFP_NOFS); } return 0; } Loading @@ -700,39 +674,36 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, struct { struct btrfs_key ins; struct btrfs_extent_item extent_item; int i; int ret; int err; unsigned long gang[8]; int err = 0; u64 start; u64 end; struct btrfs_fs_info *info = extent_root->fs_info; btrfs_set_stack_extent_refs(&extent_item, 1); ins.offset = 1; btrfs_set_key_type(&ins, BTRFS_EXTENT_ITEM_KEY); btrfs_set_stack_extent_owner(&extent_item, extent_root->root_key.objectid); while(1) { ret = find_first_radix_bit(&info->extent_ins_radix, gang, 0, ARRAY_SIZE(gang)); if (!ret) ret = find_first_extent_bit(&info->extent_ins, 0, &start, &end, EXTENT_LOCKED); if (ret) break; for (i = 0; i < ret; i++) { ins.objectid = gang[i]; ins.objectid = start; ins.offset = end + 1 - start; err = btrfs_insert_item(trans, extent_root, &ins, &extent_item, sizeof(extent_item)); clear_radix_bit(&info->extent_ins_radix, gang[i]); WARN_ON(err); } &extent_item, sizeof(extent_item)); clear_extent_bits(&info->extent_ins, start, end, EXTENT_LOCKED, GFP_NOFS); } return 0; } static int pin_down_block(struct btrfs_root *root, u64 blocknr, int pending) { int err; int err = 0; struct extent_buffer *buf; if (!pending) { Loading @@ -748,16 +719,11 @@ static int pin_down_block(struct btrfs_root *root, u64 blocknr, int pending) } free_extent_buffer(buf); } err = set_radix_bit(&root->fs_info->pinned_radix, blocknr); if (!err) { struct btrfs_block_group_cache *cache; cache = btrfs_lookup_block_group(root->fs_info, blocknr); if (cache) cache->pinned++; } set_extent_dirty(&root->fs_info->pinned_extents, blocknr, blocknr, GFP_NOFS); } else { err = set_radix_bit(&root->fs_info->pending_del_radix, blocknr); set_extent_bits(&root->fs_info->pending_del, blocknr, blocknr, EXTENT_LOCKED, GFP_NOFS); } BUG_ON(err < 0); return 0; Loading Loading @@ -840,43 +806,28 @@ static int del_pending_extents(struct btrfs_trans_handle *trans, struct btrfs_root *extent_root) { int ret; int wret; int err = 0; unsigned long gang[4]; int i; struct radix_tree_root *pending_radix; struct radix_tree_root *pinned_radix; struct btrfs_block_group_cache *cache; u64 start; u64 end; struct extent_map_tree *pending_del; struct extent_map_tree *pinned_extents; pending_radix = &extent_root->fs_info->pending_del_radix; pinned_radix = &extent_root->fs_info->pinned_radix; pending_del = &extent_root->fs_info->pending_del; pinned_extents = &extent_root->fs_info->pinned_extents; while(1) { ret = find_first_radix_bit(pending_radix, gang, 0, ARRAY_SIZE(gang)); if (!ret) ret = find_first_extent_bit(pending_del, 0, &start, &end, EXTENT_LOCKED); if (ret) break; for (i = 0; i < ret; i++) { wret = set_radix_bit(pinned_radix, gang[i]); if (wret == 0) { cache = btrfs_lookup_block_group(extent_root->fs_info, gang[i]); if (cache) cache->pinned++; } if (wret < 0) { printk(KERN_CRIT "set_radix_bit, err %d\n", wret); BUG_ON(wret < 0); } wret = clear_radix_bit(pending_radix, gang[i]); BUG_ON(wret); wret = __free_extent(trans, extent_root, gang[i], 1, 0, 0); if (wret) err = wret; } set_extent_dirty(pinned_extents, start, end, GFP_NOFS); clear_extent_bits(pending_del, start, end, EXTENT_LOCKED, GFP_NOFS); ret = __free_extent(trans, extent_root, start, end + 1 - start, 0, 0); if (ret) err = ret; } return err; } Loading Loading @@ -920,7 +871,6 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root u64 hole_size = 0; int slot = 0; u64 last_block = 0; u64 test_block; u64 orig_search_start = search_start; int start_found; struct extent_buffer *l; Loading Loading @@ -1059,13 +1009,15 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root if (ins->objectid + num_blocks >= search_end) goto enospc; for (test_block = ins->objectid; test_block < ins->objectid + num_blocks; test_block++) { if (test_radix_bit(&info->pinned_radix, test_block) || test_radix_bit(&info->extent_ins_radix, test_block)) { search_start = test_block + 1; if (test_range_bit(&info->extent_ins, ins->objectid, ins->objectid + num_blocks -1, EXTENT_LOCKED, 0)) { search_start = ins->objectid + num_blocks; goto new_group; } if (test_range_bit(&info->pinned_extents, ins->objectid, ins->objectid + num_blocks -1, EXTENT_DIRTY, 0)) { search_start = ins->objectid + num_blocks; goto new_group; } if (exclude_nr > 0 && (ins->objectid + num_blocks > exclude_start && ins->objectid < exclude_start + exclude_nr)) { Loading Loading @@ -1156,7 +1108,9 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans, if (root == extent_root) { BUG_ON(num_blocks != 1); set_radix_bit(&root->fs_info->extent_ins_radix, ins->objectid); set_extent_bits(&root->fs_info->extent_ins, ins->objectid, ins->objectid + ins->offset - 1, EXTENT_LOCKED, GFP_NOFS); goto update_block; } Loading Loading @@ -1557,9 +1511,6 @@ int btrfs_read_block_groups(struct btrfs_root *root) btrfs_item_ptr_offset(leaf, path->slots[0]), sizeof(cache->item)); memcpy(&cache->key, &found_key, sizeof(found_key)); cache->last_alloc = cache->key.objectid; cache->first_free = cache->key.objectid; cache->pinned = 0; cache->cached = 0; key.objectid = found_key.objectid + found_key.offset; Loading fs/btrfs/extent_map.c +3 −2 Original line number Diff line number Diff line Loading @@ -1188,7 +1188,7 @@ int get_state_private(struct extent_map_tree *tree, u64 start, u64 *private) * has the bits set. Otherwise, 1 is returned if any bit in the * range is found set. */ static int test_range_bit(struct extent_map_tree *tree, u64 start, u64 end, int test_range_bit(struct extent_map_tree *tree, u64 start, u64 end, int bits, int filled) { struct extent_state *state = NULL; Loading Loading @@ -1222,6 +1222,7 @@ static int test_range_bit(struct extent_map_tree *tree, u64 start, u64 end, read_unlock_irq(&tree->lock); return bitset; } EXPORT_SYMBOL(test_range_bit); /* * helper function to set a given page up to date if all the Loading fs/btrfs/extent_map.h +3 −1 Original line number Diff line number Diff line Loading @@ -95,7 +95,9 @@ int extent_read_full_page(struct extent_map_tree *tree, struct page *page, get_extent_t *get_extent); void __init extent_map_init(void); void __exit extent_map_exit(void); int extent_clean_all_trees(struct extent_map_tree *tree); int test_range_bit(struct extent_map_tree *tree, u64 start, u64 end, int bits, int filled); int clear_extent_bits(struct extent_map_tree *tree, u64 start, u64 end, int bits, gfp_t mask); int set_extent_bits(struct extent_map_tree *tree, u64 start, u64 end, Loading Loading
fs/btrfs/ctree.h +7 −9 Original line number Diff line number Diff line Loading @@ -283,10 +283,6 @@ struct btrfs_block_group_item { struct btrfs_block_group_cache { struct btrfs_key key; struct btrfs_block_group_item item; u64 first_free; u64 last_alloc; u64 pinned; u64 last_prealloc; int data; int cached; }; Loading @@ -296,11 +292,13 @@ struct btrfs_fs_info { struct btrfs_root *extent_root; struct btrfs_root *tree_root; struct radix_tree_root fs_roots_radix; struct radix_tree_root pending_del_radix; struct radix_tree_root pinned_radix; struct radix_tree_root extent_ins_radix; struct extent_map_tree free_space_cache; struct extent_map_tree block_group_cache; struct extent_map_tree pinned_extents; struct extent_map_tree pending_del; struct extent_map_tree extent_ins; u64 generation; u64 last_trans_committed; struct btrfs_transaction *running_transaction; Loading Loading @@ -926,7 +924,7 @@ static inline int btrfs_set_root_name(struct btrfs_root *root, /* extent-tree.c */ int btrfs_extent_post_op(struct btrfs_trans_handle *trans, struct btrfs_root *root); int btrfs_copy_pinned(struct btrfs_root *root, struct radix_tree_root *copy); int btrfs_copy_pinned(struct btrfs_root *root, struct extent_map_tree *copy); struct btrfs_block_group_cache *btrfs_lookup_block_group(struct btrfs_fs_info *info, u64 blocknr); Loading @@ -949,7 +947,7 @@ int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root *root, u64 blocknr, u64 num_blocks, int pin); int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct radix_tree_root *unpin_radix); struct extent_map_tree *unpin); int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, u64 blocknr, u64 num_blocks); Loading
fs/btrfs/disk-io.c +6 −3 Original line number Diff line number Diff line Loading @@ -432,9 +432,6 @@ struct btrfs_root *open_ctree(struct super_block *sb) err = -ENOMEM; goto fail; } init_bit_radix(&fs_info->pinned_radix); init_bit_radix(&fs_info->pending_del_radix); init_bit_radix(&fs_info->extent_ins_radix); INIT_RADIX_TREE(&fs_info->fs_roots_radix, GFP_NOFS); INIT_LIST_HEAD(&fs_info->trans_list); INIT_LIST_HEAD(&fs_info->dead_roots); Loading @@ -458,6 +455,12 @@ struct btrfs_root *open_ctree(struct super_block *sb) fs_info->btree_inode->i_mapping, GFP_NOFS); extent_map_tree_init(&fs_info->block_group_cache, fs_info->btree_inode->i_mapping, GFP_NOFS); extent_map_tree_init(&fs_info->pinned_extents, fs_info->btree_inode->i_mapping, GFP_NOFS); extent_map_tree_init(&fs_info->pending_del, fs_info->btree_inode->i_mapping, GFP_NOFS); extent_map_tree_init(&fs_info->extent_ins, fs_info->btree_inode->i_mapping, GFP_NOFS); fs_info->do_barriers = 1; fs_info->closing = 0; Loading
fs/btrfs/extent-tree.c +72 −121 Original line number Diff line number Diff line Loading @@ -188,13 +188,13 @@ static u64 find_search_start(struct btrfs_root *root, return start; } out: return max(cache->last_alloc, search_start); return search_start; new_group: cache = btrfs_lookup_block_group(root->fs_info, last + cache->key.offset - 1); if (!cache) { return max((*cache_ret)->last_alloc, search_start); return search_start; } cache = btrfs_find_block_group(root, cache, last + cache->key.offset - 1, data, 0); Loading Loading @@ -247,16 +247,14 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root, shint = btrfs_lookup_block_group(info, search_start); if (shint && shint->data == data) { used = btrfs_block_group_used(&shint->item); if (used + shint->pinned < div_factor(shint->key.offset, factor)) { if (used < div_factor(shint->key.offset, factor)) { return shint; } } } if (hint && hint->data == data) { used = btrfs_block_group_used(&hint->item); if (used + hint->pinned < div_factor(hint->key.offset, factor)) { if (used < div_factor(hint->key.offset, factor)) { return hint; } last = hint->key.offset * 3; Loading Loading @@ -294,7 +292,7 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root, else free_check = div_factor(cache->key.offset, factor); if (used + cache->pinned < free_check) { if (used < free_check) { found_group = cache; goto found; } Loading Loading @@ -505,8 +503,6 @@ static int write_one_cache_group(struct btrfs_trans_handle *trans, return ret; if (pending_ret) return pending_ret; if (cache->data) cache->last_alloc = cache->first_free; return 0; } Loading Loading @@ -588,8 +584,6 @@ static int update_block_group(struct btrfs_trans_handle *trans, old_val = btrfs_block_group_used(&cache->item); num = min(total, cache->key.offset - block_in_group); if (alloc) { if (blocknr > cache->last_alloc) cache->last_alloc = blocknr; if (cache->data != data && old_val < (cache->key.offset >> 1)) { int bit_to_clear; Loading Loading @@ -617,8 +611,6 @@ static int update_block_group(struct btrfs_trans_handle *trans, old_val += num; } else { old_val -= num; if (blocknr < cache->first_free) cache->first_free = blocknr; if (mark_free) { set_extent_dirty(&info->free_space_cache, blocknr, blocknr + num - 1, Loading @@ -632,65 +624,47 @@ static int update_block_group(struct btrfs_trans_handle *trans, return 0; } int btrfs_copy_pinned(struct btrfs_root *root, struct radix_tree_root *copy) int btrfs_copy_pinned(struct btrfs_root *root, struct extent_map_tree *copy) { unsigned long gang[8]; u64 last = 0; struct radix_tree_root *pinned_radix = &root->fs_info->pinned_radix; u64 start; u64 end; struct extent_map_tree *pinned_extents = &root->fs_info->pinned_extents; int ret; int i; while(1) { ret = find_first_radix_bit(pinned_radix, gang, last, ARRAY_SIZE(gang)); if (!ret) ret = find_first_extent_bit(pinned_extents, last, &start, &end, EXTENT_DIRTY); if (ret) break; for (i = 0 ; i < ret; i++) { set_radix_bit(copy, gang[i]); last = gang[i] + 1; } set_extent_dirty(copy, start, end, GFP_NOFS); last = end + 1; } ret = find_first_radix_bit(&root->fs_info->extent_ins_radix, gang, 0, ARRAY_SIZE(gang)); WARN_ON(ret); return 0; } int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct radix_tree_root *unpin_radix) struct extent_map_tree *unpin) { unsigned long gang[8]; struct btrfs_block_group_cache *block_group; u64 first = 0; u64 start; u64 end; int ret; int i; struct radix_tree_root *pinned_radix = &root->fs_info->pinned_radix; struct extent_map_tree *pinned_extents = &root->fs_info->pinned_extents; struct extent_map_tree *free_space_cache; free_space_cache = &root->fs_info->free_space_cache; while(1) { ret = find_first_radix_bit(unpin_radix, gang, 0, ARRAY_SIZE(gang)); if (!ret) ret = find_first_extent_bit(unpin, 0, &start, &end, EXTENT_DIRTY); if (ret) break; if (!first) first = gang[0]; for (i = 0; i < ret; i++) { clear_radix_bit(pinned_radix, gang[i]); clear_radix_bit(unpin_radix, gang[i]); block_group = btrfs_lookup_block_group(root->fs_info, gang[i]); if (block_group) { WARN_ON(block_group->pinned == 0); block_group->pinned--; if (gang[i] < block_group->last_alloc) block_group->last_alloc = gang[i]; set_extent_dirty(free_space_cache, gang[i], gang[i], GFP_NOFS); } } clear_extent_dirty(pinned_extents, start, end, GFP_NOFS); clear_extent_dirty(unpin, start, end, GFP_NOFS); set_extent_dirty(free_space_cache, start, end, GFP_NOFS); } return 0; } Loading @@ -700,39 +674,36 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, struct { struct btrfs_key ins; struct btrfs_extent_item extent_item; int i; int ret; int err; unsigned long gang[8]; int err = 0; u64 start; u64 end; struct btrfs_fs_info *info = extent_root->fs_info; btrfs_set_stack_extent_refs(&extent_item, 1); ins.offset = 1; btrfs_set_key_type(&ins, BTRFS_EXTENT_ITEM_KEY); btrfs_set_stack_extent_owner(&extent_item, extent_root->root_key.objectid); while(1) { ret = find_first_radix_bit(&info->extent_ins_radix, gang, 0, ARRAY_SIZE(gang)); if (!ret) ret = find_first_extent_bit(&info->extent_ins, 0, &start, &end, EXTENT_LOCKED); if (ret) break; for (i = 0; i < ret; i++) { ins.objectid = gang[i]; ins.objectid = start; ins.offset = end + 1 - start; err = btrfs_insert_item(trans, extent_root, &ins, &extent_item, sizeof(extent_item)); clear_radix_bit(&info->extent_ins_radix, gang[i]); WARN_ON(err); } &extent_item, sizeof(extent_item)); clear_extent_bits(&info->extent_ins, start, end, EXTENT_LOCKED, GFP_NOFS); } return 0; } static int pin_down_block(struct btrfs_root *root, u64 blocknr, int pending) { int err; int err = 0; struct extent_buffer *buf; if (!pending) { Loading @@ -748,16 +719,11 @@ static int pin_down_block(struct btrfs_root *root, u64 blocknr, int pending) } free_extent_buffer(buf); } err = set_radix_bit(&root->fs_info->pinned_radix, blocknr); if (!err) { struct btrfs_block_group_cache *cache; cache = btrfs_lookup_block_group(root->fs_info, blocknr); if (cache) cache->pinned++; } set_extent_dirty(&root->fs_info->pinned_extents, blocknr, blocknr, GFP_NOFS); } else { err = set_radix_bit(&root->fs_info->pending_del_radix, blocknr); set_extent_bits(&root->fs_info->pending_del, blocknr, blocknr, EXTENT_LOCKED, GFP_NOFS); } BUG_ON(err < 0); return 0; Loading Loading @@ -840,43 +806,28 @@ static int del_pending_extents(struct btrfs_trans_handle *trans, struct btrfs_root *extent_root) { int ret; int wret; int err = 0; unsigned long gang[4]; int i; struct radix_tree_root *pending_radix; struct radix_tree_root *pinned_radix; struct btrfs_block_group_cache *cache; u64 start; u64 end; struct extent_map_tree *pending_del; struct extent_map_tree *pinned_extents; pending_radix = &extent_root->fs_info->pending_del_radix; pinned_radix = &extent_root->fs_info->pinned_radix; pending_del = &extent_root->fs_info->pending_del; pinned_extents = &extent_root->fs_info->pinned_extents; while(1) { ret = find_first_radix_bit(pending_radix, gang, 0, ARRAY_SIZE(gang)); if (!ret) ret = find_first_extent_bit(pending_del, 0, &start, &end, EXTENT_LOCKED); if (ret) break; for (i = 0; i < ret; i++) { wret = set_radix_bit(pinned_radix, gang[i]); if (wret == 0) { cache = btrfs_lookup_block_group(extent_root->fs_info, gang[i]); if (cache) cache->pinned++; } if (wret < 0) { printk(KERN_CRIT "set_radix_bit, err %d\n", wret); BUG_ON(wret < 0); } wret = clear_radix_bit(pending_radix, gang[i]); BUG_ON(wret); wret = __free_extent(trans, extent_root, gang[i], 1, 0, 0); if (wret) err = wret; } set_extent_dirty(pinned_extents, start, end, GFP_NOFS); clear_extent_bits(pending_del, start, end, EXTENT_LOCKED, GFP_NOFS); ret = __free_extent(trans, extent_root, start, end + 1 - start, 0, 0); if (ret) err = ret; } return err; } Loading Loading @@ -920,7 +871,6 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root u64 hole_size = 0; int slot = 0; u64 last_block = 0; u64 test_block; u64 orig_search_start = search_start; int start_found; struct extent_buffer *l; Loading Loading @@ -1059,13 +1009,15 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root if (ins->objectid + num_blocks >= search_end) goto enospc; for (test_block = ins->objectid; test_block < ins->objectid + num_blocks; test_block++) { if (test_radix_bit(&info->pinned_radix, test_block) || test_radix_bit(&info->extent_ins_radix, test_block)) { search_start = test_block + 1; if (test_range_bit(&info->extent_ins, ins->objectid, ins->objectid + num_blocks -1, EXTENT_LOCKED, 0)) { search_start = ins->objectid + num_blocks; goto new_group; } if (test_range_bit(&info->pinned_extents, ins->objectid, ins->objectid + num_blocks -1, EXTENT_DIRTY, 0)) { search_start = ins->objectid + num_blocks; goto new_group; } if (exclude_nr > 0 && (ins->objectid + num_blocks > exclude_start && ins->objectid < exclude_start + exclude_nr)) { Loading Loading @@ -1156,7 +1108,9 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans, if (root == extent_root) { BUG_ON(num_blocks != 1); set_radix_bit(&root->fs_info->extent_ins_radix, ins->objectid); set_extent_bits(&root->fs_info->extent_ins, ins->objectid, ins->objectid + ins->offset - 1, EXTENT_LOCKED, GFP_NOFS); goto update_block; } Loading Loading @@ -1557,9 +1511,6 @@ int btrfs_read_block_groups(struct btrfs_root *root) btrfs_item_ptr_offset(leaf, path->slots[0]), sizeof(cache->item)); memcpy(&cache->key, &found_key, sizeof(found_key)); cache->last_alloc = cache->key.objectid; cache->first_free = cache->key.objectid; cache->pinned = 0; cache->cached = 0; key.objectid = found_key.objectid + found_key.offset; Loading
fs/btrfs/extent_map.c +3 −2 Original line number Diff line number Diff line Loading @@ -1188,7 +1188,7 @@ int get_state_private(struct extent_map_tree *tree, u64 start, u64 *private) * has the bits set. Otherwise, 1 is returned if any bit in the * range is found set. */ static int test_range_bit(struct extent_map_tree *tree, u64 start, u64 end, int test_range_bit(struct extent_map_tree *tree, u64 start, u64 end, int bits, int filled) { struct extent_state *state = NULL; Loading Loading @@ -1222,6 +1222,7 @@ static int test_range_bit(struct extent_map_tree *tree, u64 start, u64 end, read_unlock_irq(&tree->lock); return bitset; } EXPORT_SYMBOL(test_range_bit); /* * helper function to set a given page up to date if all the Loading
fs/btrfs/extent_map.h +3 −1 Original line number Diff line number Diff line Loading @@ -95,7 +95,9 @@ int extent_read_full_page(struct extent_map_tree *tree, struct page *page, get_extent_t *get_extent); void __init extent_map_init(void); void __exit extent_map_exit(void); int extent_clean_all_trees(struct extent_map_tree *tree); int test_range_bit(struct extent_map_tree *tree, u64 start, u64 end, int bits, int filled); int clear_extent_bits(struct extent_map_tree *tree, u64 start, u64 end, int bits, gfp_t mask); int set_extent_bits(struct extent_map_tree *tree, u64 start, u64 end, Loading