diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-04-02 10:50:19 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@hera.kernel.org> | 2007-04-02 10:50:19 -0400 |
commit | 2c90e5d658424bc71b111eb5a972240d5d06fe86 (patch) | |
tree | f46b830654af0f67ef1691353fe4d79943a05465 /fs/btrfs/transaction.c | |
parent | d6025579531b7ea170ba283b171ff7a6bf7d0e12 (diff) |
Btrfs: still corruption hunting
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/transaction.c')
-rw-r--r-- | fs/btrfs/transaction.c | 39 |
1 files changed, 27 insertions, 12 deletions
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 84c4e278ce2e..72b52e1e0b1b 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -5,13 +5,20 @@ | |||
5 | #include "transaction.h" | 5 | #include "transaction.h" |
6 | 6 | ||
7 | static int total_trans = 0; | 7 | static int total_trans = 0; |
8 | extern struct kmem_cache *btrfs_trans_handle_cachep; | ||
9 | extern struct kmem_cache *btrfs_transaction_cachep; | ||
10 | |||
11 | #define TRANS_MAGIC 0xE1E10E | ||
8 | static void put_transaction(struct btrfs_transaction *transaction) | 12 | static void put_transaction(struct btrfs_transaction *transaction) |
9 | { | 13 | { |
14 | WARN_ON(transaction->use_count == 0); | ||
10 | transaction->use_count--; | 15 | transaction->use_count--; |
16 | WARN_ON(transaction->magic != TRANS_MAGIC); | ||
11 | if (transaction->use_count == 0) { | 17 | if (transaction->use_count == 0) { |
12 | WARN_ON(total_trans == 0); | 18 | WARN_ON(total_trans == 0); |
13 | total_trans--; | 19 | total_trans--; |
14 | kfree(transaction); | 20 | memset(transaction, 0, sizeof(*transaction)); |
21 | kmem_cache_free(btrfs_transaction_cachep, transaction); | ||
15 | } | 22 | } |
16 | } | 23 | } |
17 | 24 | ||
@@ -20,7 +27,8 @@ static int join_transaction(struct btrfs_root *root) | |||
20 | struct btrfs_transaction *cur_trans; | 27 | struct btrfs_transaction *cur_trans; |
21 | cur_trans = root->fs_info->running_transaction; | 28 | cur_trans = root->fs_info->running_transaction; |
22 | if (!cur_trans) { | 29 | if (!cur_trans) { |
23 | cur_trans = kmalloc(sizeof(*cur_trans), GFP_NOFS); | 30 | cur_trans = kmem_cache_alloc(btrfs_transaction_cachep, |
31 | GFP_NOFS); | ||
24 | total_trans++; | 32 | total_trans++; |
25 | BUG_ON(!cur_trans); | 33 | BUG_ON(!cur_trans); |
26 | root->fs_info->running_transaction = cur_trans; | 34 | root->fs_info->running_transaction = cur_trans; |
@@ -28,6 +36,7 @@ static int join_transaction(struct btrfs_root *root) | |||
28 | cur_trans->transid = root->root_key.offset + 1; | 36 | cur_trans->transid = root->root_key.offset + 1; |
29 | init_waitqueue_head(&cur_trans->writer_wait); | 37 | init_waitqueue_head(&cur_trans->writer_wait); |
30 | init_waitqueue_head(&cur_trans->commit_wait); | 38 | init_waitqueue_head(&cur_trans->commit_wait); |
39 | cur_trans->magic = TRANS_MAGIC; | ||
31 | cur_trans->in_commit = 0; | 40 | cur_trans->in_commit = 0; |
32 | cur_trans->use_count = 1; | 41 | cur_trans->use_count = 1; |
33 | cur_trans->commit_done = 0; | 42 | cur_trans->commit_done = 0; |
@@ -39,7 +48,8 @@ static int join_transaction(struct btrfs_root *root) | |||
39 | struct btrfs_trans_handle *btrfs_start_transaction(struct btrfs_root *root, | 48 | struct btrfs_trans_handle *btrfs_start_transaction(struct btrfs_root *root, |
40 | int num_blocks) | 49 | int num_blocks) |
41 | { | 50 | { |
42 | struct btrfs_trans_handle *h = kmalloc(sizeof(*h), GFP_NOFS); | 51 | struct btrfs_trans_handle *h = |
52 | kmem_cache_alloc(btrfs_trans_handle_cachep, GFP_NOFS); | ||
43 | int ret; | 53 | int ret; |
44 | 54 | ||
45 | mutex_lock(&root->fs_info->trans_mutex); | 55 | mutex_lock(&root->fs_info->trans_mutex); |
@@ -51,6 +61,7 @@ struct btrfs_trans_handle *btrfs_start_transaction(struct btrfs_root *root, | |||
51 | h->blocks_used = 0; | 61 | h->blocks_used = 0; |
52 | root->fs_info->running_transaction->use_count++; | 62 | root->fs_info->running_transaction->use_count++; |
53 | mutex_unlock(&root->fs_info->trans_mutex); | 63 | mutex_unlock(&root->fs_info->trans_mutex); |
64 | h->magic = h->magic2 = TRANS_MAGIC; | ||
54 | return h; | 65 | return h; |
55 | } | 66 | } |
56 | 67 | ||
@@ -58,6 +69,8 @@ int btrfs_end_transaction(struct btrfs_trans_handle *trans, | |||
58 | struct btrfs_root *root) | 69 | struct btrfs_root *root) |
59 | { | 70 | { |
60 | struct btrfs_transaction *cur_trans; | 71 | struct btrfs_transaction *cur_trans; |
72 | WARN_ON(trans->magic != TRANS_MAGIC); | ||
73 | WARN_ON(trans->magic2 != TRANS_MAGIC); | ||
61 | mutex_lock(&root->fs_info->trans_mutex); | 74 | mutex_lock(&root->fs_info->trans_mutex); |
62 | cur_trans = root->fs_info->running_transaction; | 75 | cur_trans = root->fs_info->running_transaction; |
63 | WARN_ON(cur_trans->num_writers < 1); | 76 | WARN_ON(cur_trans->num_writers < 1); |
@@ -67,7 +80,7 @@ int btrfs_end_transaction(struct btrfs_trans_handle *trans, | |||
67 | put_transaction(cur_trans); | 80 | put_transaction(cur_trans); |
68 | mutex_unlock(&root->fs_info->trans_mutex); | 81 | mutex_unlock(&root->fs_info->trans_mutex); |
69 | memset(trans, 0, sizeof(*trans)); | 82 | memset(trans, 0, sizeof(*trans)); |
70 | kfree(trans); | 83 | kmem_cache_free(btrfs_trans_handle_cachep, trans); |
71 | return 0; | 84 | return 0; |
72 | } | 85 | } |
73 | 86 | ||
@@ -75,7 +88,7 @@ int btrfs_end_transaction(struct btrfs_trans_handle *trans, | |||
75 | int btrfs_write_and_wait_transaction(struct btrfs_trans_handle *trans, | 88 | int btrfs_write_and_wait_transaction(struct btrfs_trans_handle *trans, |
76 | struct btrfs_root *root) | 89 | struct btrfs_root *root) |
77 | { | 90 | { |
78 | filemap_write_and_wait(root->fs_info->btree_inode->i_mapping); | 91 | filemap_write_and_wait(root->fs_info->sb->s_bdev->bd_inode->i_mapping); |
79 | return 0; | 92 | return 0; |
80 | } | 93 | } |
81 | 94 | ||
@@ -137,6 +150,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
137 | 150 | ||
138 | mutex_lock(&root->fs_info->trans_mutex); | 151 | mutex_lock(&root->fs_info->trans_mutex); |
139 | if (trans->transaction->in_commit) { | 152 | if (trans->transaction->in_commit) { |
153 | printk("already in commit!, waiting\n"); | ||
140 | cur_trans = trans->transaction; | 154 | cur_trans = trans->transaction; |
141 | trans->transaction->use_count++; | 155 | trans->transaction->use_count++; |
142 | btrfs_end_transaction(trans, root); | 156 | btrfs_end_transaction(trans, root); |
@@ -146,7 +160,10 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
146 | mutex_unlock(&root->fs_info->trans_mutex); | 160 | mutex_unlock(&root->fs_info->trans_mutex); |
147 | return 0; | 161 | return 0; |
148 | } | 162 | } |
163 | cur_trans = trans->transaction; | ||
164 | trans->transaction->in_commit = 1; | ||
149 | while (trans->transaction->num_writers > 1) { | 165 | while (trans->transaction->num_writers > 1) { |
166 | WARN_ON(cur_trans != trans->transaction); | ||
150 | prepare_to_wait(&trans->transaction->writer_wait, &wait, | 167 | prepare_to_wait(&trans->transaction->writer_wait, &wait, |
151 | TASK_UNINTERRUPTIBLE); | 168 | TASK_UNINTERRUPTIBLE); |
152 | if (trans->transaction->num_writers <= 1) | 169 | if (trans->transaction->num_writers <= 1) |
@@ -154,15 +171,15 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
154 | mutex_unlock(&root->fs_info->trans_mutex); | 171 | mutex_unlock(&root->fs_info->trans_mutex); |
155 | schedule(); | 172 | schedule(); |
156 | mutex_lock(&root->fs_info->trans_mutex); | 173 | mutex_lock(&root->fs_info->trans_mutex); |
174 | finish_wait(&trans->transaction->writer_wait, &wait); | ||
157 | } | 175 | } |
158 | finish_wait(&trans->transaction->writer_wait, &wait); | 176 | finish_wait(&trans->transaction->writer_wait, &wait); |
159 | 177 | WARN_ON(cur_trans != trans->transaction); | |
160 | if (root->node != root->commit_root) { | 178 | if (root->node != root->commit_root) { |
161 | memcpy(&snap_key, &root->root_key, sizeof(snap_key)); | 179 | memcpy(&snap_key, &root->root_key, sizeof(snap_key)); |
162 | root->root_key.offset++; | 180 | root->root_key.offset++; |
163 | } | 181 | } |
164 | 182 | ||
165 | |||
166 | if (btrfs_root_blocknr(&root->root_item) != root->node->b_blocknr) { | 183 | if (btrfs_root_blocknr(&root->root_item) != root->node->b_blocknr) { |
167 | btrfs_set_root_blocknr(&root->root_item, root->node->b_blocknr); | 184 | btrfs_set_root_blocknr(&root->root_item, root->node->b_blocknr); |
168 | ret = btrfs_insert_root(trans, root->fs_info->tree_root, | 185 | ret = btrfs_insert_root(trans, root->fs_info->tree_root, |
@@ -172,22 +189,21 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
172 | 189 | ||
173 | ret = btrfs_commit_tree_roots(trans, root); | 190 | ret = btrfs_commit_tree_roots(trans, root); |
174 | BUG_ON(ret); | 191 | BUG_ON(ret); |
175 | |||
176 | cur_trans = root->fs_info->running_transaction; | 192 | cur_trans = root->fs_info->running_transaction; |
177 | root->fs_info->running_transaction = NULL; | 193 | root->fs_info->running_transaction = NULL; |
178 | mutex_unlock(&root->fs_info->trans_mutex); | 194 | mutex_unlock(&root->fs_info->trans_mutex); |
179 | |||
180 | ret = btrfs_write_and_wait_transaction(trans, root); | 195 | ret = btrfs_write_and_wait_transaction(trans, root); |
181 | BUG_ON(ret); | 196 | BUG_ON(ret); |
182 | 197 | ||
183 | write_ctree_super(trans, root); | 198 | write_ctree_super(trans, root); |
184 | btrfs_finish_extent_commit(trans, root); | 199 | btrfs_finish_extent_commit(trans, root); |
185 | mutex_lock(&root->fs_info->trans_mutex); | 200 | mutex_lock(&root->fs_info->trans_mutex); |
201 | cur_trans->commit_done = 1; | ||
202 | wake_up(&cur_trans->commit_wait); | ||
186 | put_transaction(cur_trans); | 203 | put_transaction(cur_trans); |
187 | put_transaction(cur_trans); | 204 | put_transaction(cur_trans); |
188 | mutex_unlock(&root->fs_info->trans_mutex); | 205 | mutex_unlock(&root->fs_info->trans_mutex); |
189 | kfree(trans); | 206 | kmem_cache_free(btrfs_trans_handle_cachep, trans); |
190 | |||
191 | if (root->node != root->commit_root) { | 207 | if (root->node != root->commit_root) { |
192 | trans = btrfs_start_transaction(root, 1); | 208 | trans = btrfs_start_transaction(root, 1); |
193 | snap = root->commit_root; | 209 | snap = root->commit_root; |
@@ -203,7 +219,6 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
203 | ret = btrfs_end_transaction(trans, root); | 219 | ret = btrfs_end_transaction(trans, root); |
204 | BUG_ON(ret); | 220 | BUG_ON(ret); |
205 | } | 221 | } |
206 | |||
207 | return ret; | 222 | return ret; |
208 | } | 223 | } |
209 | 224 | ||