Commit 81f7eb00 authored by Jeff Mahoney's avatar Jeff Mahoney Committed by David Sterba
Browse files

btrfs: destroy qgroup extent records on transaction abort



We clean up the delayed references when we abort a transaction but we
leave the pending qgroup extent records behind, leaking memory.

This patch destroys the extent records when we destroy the delayed refs
and makes sure ensure they're gone before releasing the transaction.

Fixes: 3368d001 ("btrfs: qgroup: Record possible quota-related extent for qgroup.")
CC: stable@vger.kernel.org # 4.4+
Reviewed-by: default avatarJosef Bacik <josef@toxicpanda.com>
Signed-off-by: default avatarJeff Mahoney <jeffm@suse.com>
[ Rebased to latest upstream, remove to_qgroup() helper, use
  rbtree_postorder_for_each_entry_safe() wrapper ]
Signed-off-by: default avatarQu Wenruo <wqu@suse.com>
Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 52e29e33
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -4276,6 +4276,7 @@ static int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans,
		cond_resched();
		spin_lock(&delayed_refs->lock);
	}
	btrfs_qgroup_destroy_extent_records(trans);

	spin_unlock(&delayed_refs->lock);

+13 −0
Original line number Diff line number Diff line
@@ -4002,3 +4002,16 @@ out:
	}
	return ret;
}

void btrfs_qgroup_destroy_extent_records(struct btrfs_transaction *trans)
{
	struct btrfs_qgroup_extent_record *entry;
	struct btrfs_qgroup_extent_record *next;
	struct rb_root *root;

	root = &trans->delayed_refs.dirty_extent_root;
	rbtree_postorder_for_each_entry_safe(entry, next, root, node) {
		ulist_free(entry->old_roots);
		kfree(entry);
	}
}
+1 −0
Original line number Diff line number Diff line
@@ -414,5 +414,6 @@ int btrfs_qgroup_add_swapped_blocks(struct btrfs_trans_handle *trans,
		u64 last_snapshot);
int btrfs_qgroup_trace_subtree_after_cow(struct btrfs_trans_handle *trans,
		struct btrfs_root *root, struct extent_buffer *eb);
void btrfs_qgroup_destroy_extent_records(struct btrfs_transaction *trans);

#endif
+2 −0
Original line number Diff line number Diff line
@@ -121,6 +121,8 @@ void btrfs_put_transaction(struct btrfs_transaction *transaction)
		BUG_ON(!list_empty(&transaction->list));
		WARN_ON(!RB_EMPTY_ROOT(
				&transaction->delayed_refs.href_root.rb_root));
		WARN_ON(!RB_EMPTY_ROOT(
				&transaction->delayed_refs.dirty_extent_root));
		if (transaction->delayed_refs.pending_csums)
			btrfs_err(transaction->fs_info,
				  "pending csums is %llu",