};
static int finish_current_insert(struct btrfs_trans_handle *trans, struct
- btrfs_root *extent_root);
+ btrfs_root *extent_root, int all);
static int del_pending_extents(struct btrfs_trans_handle *trans, struct
- btrfs_root *extent_root);
+ btrfs_root *extent_root, int all);
static struct btrfs_block_group_cache *
__btrfs_find_block_group(struct btrfs_root *root,
struct btrfs_block_group_cache *hint,
parent, ref_root, ref_generation,
owner_objectid);
BUG_ON(ret);
- finish_current_insert(trans, extent_root);
- del_pending_extents(trans, extent_root);
+ finish_current_insert(trans, extent_root, 0);
+ del_pending_extents(trans, extent_root, 0);
out:
btrfs_free_path(path);
return ret;
ref_root, ref_generation,
owner_objectid);
BUG_ON(ret);
- finish_current_insert(trans, root->fs_info->extent_root);
- del_pending_extents(trans, root->fs_info->extent_root);
+ finish_current_insert(trans, root->fs_info->extent_root, 0);
+ del_pending_extents(trans, root->fs_info->extent_root, 0);
btrfs_free_path(path);
return 0;
int btrfs_extent_post_op(struct btrfs_trans_handle *trans,
struct btrfs_root *root)
{
- finish_current_insert(trans, root->fs_info->extent_root);
- del_pending_extents(trans, root->fs_info->extent_root);
+ finish_current_insert(trans, root->fs_info->extent_root, 1);
+ del_pending_extents(trans, root->fs_info->extent_root, 1);
return 0;
}
btrfs_mark_buffer_dirty(leaf);
btrfs_release_path(extent_root, path);
fail:
- finish_current_insert(trans, extent_root);
- pending_ret = del_pending_extents(trans, extent_root);
+ finish_current_insert(trans, extent_root, 0);
+ pending_ret = del_pending_extents(trans, extent_root, 0);
if (ret)
return ret;
if (pending_ret)
}
static int finish_current_insert(struct btrfs_trans_handle *trans,
- struct btrfs_root *extent_root)
+ struct btrfs_root *extent_root, int all)
{
u64 start;
u64 end;
&end, EXTENT_WRITEBACK);
if (ret) {
mutex_unlock(&info->extent_ins_mutex);
- if (search) {
+ if (search && all) {
search = 0;
continue;
}
ret = try_lock_extent(&info->extent_ins, start, end, GFP_NOFS);
if (!ret) {
- search = end+1;
+ search = end + 1;
mutex_unlock(&info->extent_ins_mutex);
cond_resched();
continue;
}
kfree(extent_op);
unlock_extent(&info->extent_ins, start, end, GFP_NOFS);
- search = 0;
+ if (all)
+ search = 0;
+ else
+ search = end + 1;
cond_resched();
}
#endif
}
btrfs_free_path(path);
- finish_current_insert(trans, extent_root);
+ finish_current_insert(trans, extent_root, 0);
return ret;
}
* them from the extent map
*/
static int del_pending_extents(struct btrfs_trans_handle *trans, struct
- btrfs_root *extent_root)
+ btrfs_root *extent_root, int all)
{
int ret;
int err = 0;
EXTENT_WRITEBACK);
if (ret) {
mutex_unlock(&info->extent_ins_mutex);
- if (search) {
+ if (all && search) {
search = 0;
continue;
}
err = ret;
unlock_extent(extent_ins, start, end, GFP_NOFS);
- search = 0;
+ if (all)
+ search = 0;
+ else
+ search = end + 1;
cond_resched();
}
return err;
root_objectid, ref_generation,
owner_objectid, pin, pin == 0);
- finish_current_insert(trans, root->fs_info->extent_root);
- pending_ret = del_pending_extents(trans, root->fs_info->extent_root);
+ finish_current_insert(trans, root->fs_info->extent_root, 0);
+ pending_ret = del_pending_extents(trans, root->fs_info->extent_root, 0);
return ret ? ret : pending_ret;
}
trans->alloc_exclude_start = 0;
trans->alloc_exclude_nr = 0;
btrfs_free_path(path);
- finish_current_insert(trans, extent_root);
- pending_ret = del_pending_extents(trans, extent_root);
+ finish_current_insert(trans, extent_root, 0);
+ pending_ret = del_pending_extents(trans, extent_root, 0);
if (ret)
goto out;
sizeof(cache->item));
BUG_ON(ret);
- finish_current_insert(trans, extent_root);
- ret = del_pending_extents(trans, extent_root);
+ finish_current_insert(trans, extent_root, 0);
+ ret = del_pending_extents(trans, extent_root, 0);
BUG_ON(ret);
set_avail_alloc_bits(extent_root->fs_info, type);
u64 old_root_bytenr;
struct btrfs_root *tree_root = root->fs_info->tree_root;
+ btrfs_extent_post_op(trans, root);
btrfs_write_dirty_block_groups(trans, root);
+ btrfs_extent_post_op(trans, root);
+
while(1) {
old_root_bytenr = btrfs_root_bytenr(&root->root_item);
if (old_root_bytenr == root->node->start)
btrfs_set_root_level(&root->root_item,
btrfs_header_level(root->node));
btrfs_set_root_generation(&root->root_item, trans->transid);
+
+ btrfs_extent_post_op(trans, root);
+
ret = btrfs_update_root(trans, tree_root,
&root->root_key,
&root->root_item);
BUG_ON(ret);
btrfs_write_dirty_block_groups(trans, root);
+ btrfs_extent_post_op(trans, root);
}
return 0;
}
struct list_head *next;
struct extent_buffer *eb;
+ btrfs_extent_post_op(trans, fs_info->tree_root);
+
eb = btrfs_lock_root_node(fs_info->tree_root);
btrfs_cow_block(trans, fs_info->tree_root, eb, NULL, 0, &eb, 0);
btrfs_tree_unlock(eb);
free_extent_buffer(eb);
+ btrfs_extent_post_op(trans, fs_info->tree_root);
+
while(!list_empty(&fs_info->dirty_cowonly_roots)) {
next = fs_info->dirty_cowonly_roots.next;
list_del_init(next);
root = list_entry(next, struct btrfs_root, dirty_list);
+
update_cowonly_root(trans, root);
}
return 0;