diff options
Diffstat (limited to 'fs/btrfs/transaction.c')
| -rw-r--r-- | fs/btrfs/transaction.c | 56 | 
1 files changed, 35 insertions, 21 deletions
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 2dbf1c1f56e..cdbb5022da5 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c @@ -40,6 +40,12 @@ static noinline void put_transaction(struct btrfs_transaction *transaction)  	}  } +static noinline void switch_commit_root(struct btrfs_root *root) +{ +	free_extent_buffer(root->commit_root); +	root->commit_root = btrfs_root_node(root); +} +  /*   * either allocate a new transaction or hop into the existing one   */ @@ -444,9 +450,6 @@ static int update_cowonly_root(struct btrfs_trans_handle *trans,  	btrfs_write_dirty_block_groups(trans, root); -	ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1); -	BUG_ON(ret); -  	while (1) {  		old_root_bytenr = btrfs_root_bytenr(&root->root_item);  		if (old_root_bytenr == root->node->start) @@ -457,13 +460,14 @@ static int update_cowonly_root(struct btrfs_trans_handle *trans,  					&root->root_key,  					&root->root_item);  		BUG_ON(ret); -		btrfs_write_dirty_block_groups(trans, root); -		ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1); +		ret = btrfs_write_dirty_block_groups(trans, root);  		BUG_ON(ret);  	} -	free_extent_buffer(root->commit_root); -	root->commit_root = btrfs_root_node(root); + +	if (root != root->fs_info->extent_root) +		switch_commit_root(root); +  	return 0;  } @@ -495,10 +499,12 @@ static noinline int commit_cowonly_roots(struct btrfs_trans_handle *trans,  		root = list_entry(next, struct btrfs_root, dirty_list);  		update_cowonly_root(trans, root); - -		ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1); -		BUG_ON(ret);  	} + +	down_write(&fs_info->extent_commit_sem); +	switch_commit_root(fs_info->extent_root); +	up_write(&fs_info->extent_commit_sem); +  	return 0;  } @@ -544,8 +550,7 @@ static noinline int commit_fs_roots(struct btrfs_trans_handle *trans,  			btrfs_update_reloc_root(trans, root);  			if (root->commit_root != root->node) { -				free_extent_buffer(root->commit_root); -				root->commit_root = btrfs_root_node(root); +				switch_commit_root(root);  				btrfs_set_root_node(&root->root_item,  						    root->node);  			} @@ -852,6 +857,16 @@ static void update_super_roots(struct btrfs_root *root)  	super->root_level = root_item->level;  } +int btrfs_transaction_in_commit(struct btrfs_fs_info *info) +{ +	int ret = 0; +	spin_lock(&info->new_trans_lock); +	if (info->running_transaction) +		ret = info->running_transaction->in_commit; +	spin_unlock(&info->new_trans_lock); +	return ret; +} +  int btrfs_commit_transaction(struct btrfs_trans_handle *trans,  			     struct btrfs_root *root)  { @@ -943,9 +958,11 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,  		mutex_unlock(&root->fs_info->trans_mutex); -		if (flush_on_commit || snap_pending) { -			if (flush_on_commit) -				btrfs_start_delalloc_inodes(root); +		if (flush_on_commit) { +			btrfs_start_delalloc_inodes(root); +			ret = btrfs_wait_ordered_extents(root, 0); +			BUG_ON(ret); +		} else if (snap_pending) {  			ret = btrfs_wait_ordered_extents(root, 1);  			BUG_ON(ret);  		} @@ -1009,15 +1026,11 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,  	btrfs_set_root_node(&root->fs_info->tree_root->root_item,  			    root->fs_info->tree_root->node); -	free_extent_buffer(root->fs_info->tree_root->commit_root); -	root->fs_info->tree_root->commit_root = -				btrfs_root_node(root->fs_info->tree_root); +	switch_commit_root(root->fs_info->tree_root);  	btrfs_set_root_node(&root->fs_info->chunk_root->root_item,  			    root->fs_info->chunk_root->node); -	free_extent_buffer(root->fs_info->chunk_root->commit_root); -	root->fs_info->chunk_root->commit_root = -				btrfs_root_node(root->fs_info->chunk_root); +	switch_commit_root(root->fs_info->chunk_root);  	update_super_roots(root); @@ -1057,6 +1070,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,  	cur_trans->commit_done = 1;  	root->fs_info->last_trans_committed = cur_trans->transid; +  	wake_up(&cur_trans->commit_wait);  	put_transaction(cur_trans);  |