aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFilipe Manana <fdmanana@suse.com>2015-11-27 11:12:00 -0500
committerFilipe Manana <fdmanana@suse.com>2015-12-17 05:59:48 -0500
commit7785a663c4beebdafeb300caf2818e7e6474abd1 (patch)
treefea9a8efe93a6cedb875f325b735be7ce053bcd1
parent50460e37186a2b932eacea24dca804bd1bcd2012 (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.c17
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}