diff options
Diffstat (limited to 'fs/btrfs/extent-tree.c')
| -rw-r--r-- | fs/btrfs/extent-tree.c | 17 | 
1 files changed, 16 insertions, 1 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index c0bc35f932bf..61ede335f6c3 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -5298,7 +5298,14 @@ int btrfs_drop_snapshot(struct btrfs_root *root, int update_ref, int for_reloc)  		goto out;  	} -	trans = btrfs_start_transaction(tree_root, 0); +	/* +	 * Use join to avoid potential EINTR from transaction start. See +	 * wait_reserve_ticket and the whole reservation callchain. +	 */ +	if (for_reloc) +		trans = btrfs_join_transaction(tree_root); +	else +		trans = btrfs_start_transaction(tree_root, 0);  	if (IS_ERR(trans)) {  		err = PTR_ERR(trans);  		goto out_free; @@ -5466,6 +5473,14 @@ int btrfs_drop_snapshot(struct btrfs_root *root, int update_ref, int for_reloc)  		}  	} +	/* +	 * This subvolume is going to be completely dropped, and won't be +	 * recorded as dirty roots, thus pertrans meta rsv will not be freed at +	 * commit transaction time.  So free it here manually. +	 */ +	btrfs_qgroup_convert_reserved_meta(root, INT_MAX); +	btrfs_qgroup_free_meta_all_pertrans(root); +  	if (test_bit(BTRFS_ROOT_IN_RADIX, &root->state))  		btrfs_add_dropped_root(trans, root);  	else  | 
