diff options
Diffstat (limited to 'fs/btrfs/disk-io.c')
| -rw-r--r-- | fs/btrfs/disk-io.c | 30 | 
1 files changed, 17 insertions, 13 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 02369a3c162..6d19a0a554a 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -62,7 +62,7 @@ static void btrfs_destroy_ordered_operations(struct btrfs_transaction *t,  static void btrfs_destroy_ordered_extents(struct btrfs_root *root);  static int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans,  				      struct btrfs_root *root); -static void btrfs_destroy_pending_snapshots(struct btrfs_transaction *t); +static void btrfs_evict_pending_snapshots(struct btrfs_transaction *t);  static void btrfs_destroy_delalloc_inodes(struct btrfs_root *root);  static int btrfs_destroy_marked_extents(struct btrfs_root *root,  					struct extent_io_tree *dirty_pages, @@ -1291,6 +1291,7 @@ struct btrfs_root *btrfs_create_tree(struct btrfs_trans_handle *trans,  				      0, objectid, NULL, 0, 0, 0);  	if (IS_ERR(leaf)) {  		ret = PTR_ERR(leaf); +		leaf = NULL;  		goto fail;  	} @@ -1334,11 +1335,16 @@ struct btrfs_root *btrfs_create_tree(struct btrfs_trans_handle *trans,  	btrfs_tree_unlock(leaf); +	return root; +  fail: -	if (ret) -		return ERR_PTR(ret); +	if (leaf) { +		btrfs_tree_unlock(leaf); +		free_extent_buffer(leaf); +	} +	kfree(root); -	return root; +	return ERR_PTR(ret);  }  static struct btrfs_root *alloc_log_tree(struct btrfs_trans_handle *trans, @@ -3253,7 +3259,7 @@ void btrfs_free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root)  	if (btrfs_root_refs(&root->root_item) == 0)  		synchronize_srcu(&fs_info->subvol_srcu); -	if (fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) { +	if (test_bit(BTRFS_FS_STATE_ERROR, &fs_info->fs_state)) {  		btrfs_free_log(NULL, root);  		btrfs_free_log_root_tree(NULL, fs_info);  	} @@ -3687,7 +3693,7 @@ int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans,  	return ret;  } -static void btrfs_destroy_pending_snapshots(struct btrfs_transaction *t) +static void btrfs_evict_pending_snapshots(struct btrfs_transaction *t)  {  	struct btrfs_pending_snapshot *snapshot;  	struct list_head splice; @@ -3700,10 +3706,8 @@ static void btrfs_destroy_pending_snapshots(struct btrfs_transaction *t)  		snapshot = list_entry(splice.next,  				      struct btrfs_pending_snapshot,  				      list); - +		snapshot->error = -ECANCELED;  		list_del_init(&snapshot->list); - -		kfree(snapshot);  	}  } @@ -3840,6 +3844,8 @@ void btrfs_cleanup_one_transaction(struct btrfs_transaction *cur_trans,  	cur_trans->blocked = 1;  	wake_up(&root->fs_info->transaction_blocked_wait); +	btrfs_evict_pending_snapshots(cur_trans); +  	cur_trans->blocked = 0;  	wake_up(&root->fs_info->transaction_wait); @@ -3849,8 +3855,6 @@ void btrfs_cleanup_one_transaction(struct btrfs_transaction *cur_trans,  	btrfs_destroy_delayed_inodes(root);  	btrfs_assert_delayed_root_empty(root); -	btrfs_destroy_pending_snapshots(cur_trans); -  	btrfs_destroy_marked_extents(root, &cur_trans->dirty_pages,  				     EXTENT_DIRTY);  	btrfs_destroy_pinned_extent(root, @@ -3894,6 +3898,8 @@ int btrfs_cleanup_transaction(struct btrfs_root *root)  		if (waitqueue_active(&root->fs_info->transaction_blocked_wait))  			wake_up(&root->fs_info->transaction_blocked_wait); +		btrfs_evict_pending_snapshots(t); +  		t->blocked = 0;  		smp_mb();  		if (waitqueue_active(&root->fs_info->transaction_wait)) @@ -3907,8 +3913,6 @@ int btrfs_cleanup_transaction(struct btrfs_root *root)  		btrfs_destroy_delayed_inodes(root);  		btrfs_assert_delayed_root_empty(root); -		btrfs_destroy_pending_snapshots(t); -  		btrfs_destroy_delalloc_inodes(root);  		spin_lock(&root->fs_info->trans_lock);  |