diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-03-25 11:35:08 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@hera.kernel.org> | 2007-03-25 11:35:08 -0400 |
commit | 78fae27ebf5bd35fb9b2e4213e486635eacfc0ad (patch) | |
tree | ca706d468053f33744cc38764854c2866c044cb7 /fs/btrfs/transaction.c | |
parent | d561c025ee3a0aee53a225bedce0ee35fe12f335 (diff) |
Btrfs: leak fixes, pinning fixes
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/transaction.c')
-rw-r--r-- | fs/btrfs/transaction.c | 32 |
1 files changed, 18 insertions, 14 deletions
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 4903b47c9780..46a596e345f0 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -4,12 +4,15 @@ | |||
4 | #include "disk-io.h" | 4 | #include "disk-io.h" |
5 | #include "transaction.h" | 5 | #include "transaction.h" |
6 | 6 | ||
7 | 7 | static int total_trans = 0; | |
8 | static void put_transaction(struct btrfs_transaction *transaction) | 8 | static void put_transaction(struct btrfs_transaction *transaction) |
9 | { | 9 | { |
10 | transaction->use_count--; | 10 | transaction->use_count--; |
11 | if (transaction->use_count == 0) | 11 | if (transaction->use_count == 0) { |
12 | WARN_ON(total_trans == 0); | ||
13 | total_trans--; | ||
12 | kfree(transaction); | 14 | kfree(transaction); |
15 | } | ||
13 | } | 16 | } |
14 | 17 | ||
15 | static int join_transaction(struct btrfs_root *root) | 18 | static int join_transaction(struct btrfs_root *root) |
@@ -18,6 +21,7 @@ static int join_transaction(struct btrfs_root *root) | |||
18 | cur_trans = root->fs_info->running_transaction; | 21 | cur_trans = root->fs_info->running_transaction; |
19 | if (!cur_trans) { | 22 | if (!cur_trans) { |
20 | cur_trans = kmalloc(sizeof(*cur_trans), GFP_NOFS); | 23 | cur_trans = kmalloc(sizeof(*cur_trans), GFP_NOFS); |
24 | total_trans++; | ||
21 | BUG_ON(!cur_trans); | 25 | BUG_ON(!cur_trans); |
22 | root->fs_info->running_transaction = cur_trans; | 26 | root->fs_info->running_transaction = cur_trans; |
23 | cur_trans->num_writers = 0; | 27 | cur_trans->num_writers = 0; |
@@ -108,7 +112,6 @@ static int wait_for_commit(struct btrfs_root *root, | |||
108 | struct btrfs_transaction *commit) | 112 | struct btrfs_transaction *commit) |
109 | { | 113 | { |
110 | DEFINE_WAIT(wait); | 114 | DEFINE_WAIT(wait); |
111 | commit->use_count++; | ||
112 | while(!commit->commit_done) { | 115 | while(!commit->commit_done) { |
113 | prepare_to_wait(&commit->commit_wait, &wait, | 116 | prepare_to_wait(&commit->commit_wait, &wait, |
114 | TASK_UNINTERRUPTIBLE); | 117 | TASK_UNINTERRUPTIBLE); |
@@ -126,7 +129,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
126 | struct btrfs_root *root) | 129 | struct btrfs_root *root) |
127 | { | 130 | { |
128 | int ret = 0; | 131 | int ret = 0; |
129 | struct buffer_head *snap = root->commit_root; | 132 | struct buffer_head *snap; |
130 | struct btrfs_key snap_key; | 133 | struct btrfs_key snap_key; |
131 | struct btrfs_transaction *cur_trans; | 134 | struct btrfs_transaction *cur_trans; |
132 | DEFINE_WAIT(wait); | 135 | DEFINE_WAIT(wait); |
@@ -153,15 +156,11 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
153 | } | 156 | } |
154 | finish_wait(&trans->transaction->writer_wait, &wait); | 157 | finish_wait(&trans->transaction->writer_wait, &wait); |
155 | 158 | ||
156 | cur_trans = root->fs_info->running_transaction; | ||
157 | root->fs_info->running_transaction = NULL; | ||
158 | |||
159 | if (root->node != root->commit_root) { | 159 | if (root->node != root->commit_root) { |
160 | memcpy(&snap_key, &root->root_key, sizeof(snap_key)); | 160 | memcpy(&snap_key, &root->root_key, sizeof(snap_key)); |
161 | root->root_key.offset++; | 161 | root->root_key.offset++; |
162 | } | 162 | } |
163 | 163 | ||
164 | mutex_unlock(&root->fs_info->trans_mutex); | ||
165 | 164 | ||
166 | if (btrfs_root_blocknr(&root->root_item) != root->node->b_blocknr) { | 165 | if (btrfs_root_blocknr(&root->root_item) != root->node->b_blocknr) { |
167 | btrfs_set_root_blocknr(&root->root_item, root->node->b_blocknr); | 166 | btrfs_set_root_blocknr(&root->root_item, root->node->b_blocknr); |
@@ -173,17 +172,24 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
173 | ret = btrfs_commit_tree_roots(trans, root); | 172 | ret = btrfs_commit_tree_roots(trans, root); |
174 | BUG_ON(ret); | 173 | BUG_ON(ret); |
175 | 174 | ||
175 | cur_trans = root->fs_info->running_transaction; | ||
176 | root->fs_info->running_transaction = NULL; | ||
177 | mutex_unlock(&root->fs_info->trans_mutex); | ||
178 | |||
176 | ret = btrfs_write_and_wait_transaction(trans, root); | 179 | ret = btrfs_write_and_wait_transaction(trans, root); |
177 | BUG_ON(ret); | 180 | BUG_ON(ret); |
178 | 181 | ||
179 | write_ctree_super(trans, root); | 182 | write_ctree_super(trans, root); |
180 | btrfs_finish_extent_commit(trans, root->fs_info->extent_root); | 183 | btrfs_finish_extent_commit(trans, root); |
181 | btrfs_finish_extent_commit(trans, root->fs_info->tree_root); | 184 | mutex_lock(&root->fs_info->trans_mutex); |
185 | put_transaction(cur_trans); | ||
182 | put_transaction(cur_trans); | 186 | put_transaction(cur_trans); |
187 | mutex_unlock(&root->fs_info->trans_mutex); | ||
183 | kfree(trans); | 188 | kfree(trans); |
184 | 189 | ||
185 | if (root->node != root->commit_root) { | 190 | if (root->node != root->commit_root) { |
186 | trans = btrfs_start_transaction(root, 1); | 191 | trans = btrfs_start_transaction(root, 1); |
192 | snap = root->commit_root; | ||
187 | root->commit_root = root->node; | 193 | root->commit_root = root->node; |
188 | get_bh(root->node); | 194 | get_bh(root->node); |
189 | ret = btrfs_drop_snapshot(trans, root, snap); | 195 | ret = btrfs_drop_snapshot(trans, root, snap); |
@@ -191,10 +197,8 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
191 | 197 | ||
192 | ret = btrfs_del_root(trans, root->fs_info->tree_root, | 198 | ret = btrfs_del_root(trans, root->fs_info->tree_root, |
193 | &snap_key); | 199 | &snap_key); |
194 | BUG_ON(ret); | 200 | BUG_ON(ret); root->fs_info->generation = root->root_key.offset + 1; ret = btrfs_end_transaction(trans, root); BUG_ON(ret); |
195 | root->fs_info->generation = root->root_key.offset + 1; | 201 | printk("at free, total trans %d\n", total_trans); |
196 | ret = btrfs_end_transaction(trans, root); | ||
197 | BUG_ON(ret); | ||
198 | } | 202 | } |
199 | 203 | ||
200 | return ret; | 204 | return ret; |