diff options
author | Filipe Manana <fdmanana@suse.com> | 2015-11-27 11:12:00 -0500 |
---|---|---|
committer | Filipe Manana <fdmanana@suse.com> | 2015-12-17 05:59:48 -0500 |
commit | 7785a663c4beebdafeb300caf2818e7e6474abd1 (patch) | |
tree | fea9a8efe93a6cedb875f325b735be7ce053bcd1 | |
parent | 50460e37186a2b932eacea24dca804bd1bcd2012 (diff) |
Btrfs: fix memory leaks after transaction is aborted
When a transaction is aborted, or its commit fails before writing the new
superblock and calling btrfs_finish_extent_commit(), we leak reference
counts on the block groups attached to the transaction's delete_bgs list,
because btrfs_finish_extent_commit() is never called for those two cases.
Fix this by dropping their references at btrfs_put_transaction(), which
is called when transactions are aborted (by making the transaction kthread
commit the transaction) or if their commits fail.
Signed-off-by: Filipe Manana <fdmanana@suse.com>
-rw-r--r-- | fs/btrfs/transaction.c | 17 |
1 files changed, 17 insertions, 0 deletions
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index be8eae80ff65..f85ccf634ca1 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -75,6 +75,23 @@ void btrfs_put_transaction(struct btrfs_transaction *transaction) | |||
75 | list_del_init(&em->list); | 75 | list_del_init(&em->list); |
76 | free_extent_map(em); | 76 | free_extent_map(em); |
77 | } | 77 | } |
78 | /* | ||
79 | * If any block groups are found in ->deleted_bgs then it's | ||
80 | * because the transaction was aborted and a commit did not | ||
81 | * happen (things failed before writing the new superblock | ||
82 | * and calling btrfs_finish_extent_commit()), so we can not | ||
83 | * discard the physical locations of the block groups. | ||
84 | */ | ||
85 | while (!list_empty(&transaction->deleted_bgs)) { | ||
86 | struct btrfs_block_group_cache *cache; | ||
87 | |||
88 | cache = list_first_entry(&transaction->deleted_bgs, | ||
89 | struct btrfs_block_group_cache, | ||
90 | bg_list); | ||
91 | list_del_init(&cache->bg_list); | ||
92 | btrfs_put_block_group_trimming(cache); | ||
93 | btrfs_put_block_group(cache); | ||
94 | } | ||
78 | kmem_cache_free(btrfs_transaction_cachep, transaction); | 95 | kmem_cache_free(btrfs_transaction_cachep, transaction); |
79 | } | 96 | } |
80 | } | 97 | } |