Btrfs: still corruption hunting
[safe/jmp/linux-2.6] / fs / btrfs / transaction.c
1 #include <linux/module.h>
2 #include <linux/fs.h>
3 #include "ctree.h"
4 #include "disk-io.h"
5 #include "transaction.h"
6
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
12 static void put_transaction(struct btrfs_transaction *transaction)
13 {
14         WARN_ON(transaction->use_count == 0);
15         transaction->use_count--;
16         WARN_ON(transaction->magic != TRANS_MAGIC);
17         if (transaction->use_count == 0) {
18                 WARN_ON(total_trans == 0);
19                 total_trans--;
20                 memset(transaction, 0, sizeof(*transaction));
21                 kmem_cache_free(btrfs_transaction_cachep, transaction);
22         }
23 }
24
25 static int join_transaction(struct btrfs_root *root)
26 {
27         struct btrfs_transaction *cur_trans;
28         cur_trans = root->fs_info->running_transaction;
29         if (!cur_trans) {
30                 cur_trans = kmem_cache_alloc(btrfs_transaction_cachep,
31                                              GFP_NOFS);
32                 total_trans++;
33                 BUG_ON(!cur_trans);
34                 root->fs_info->running_transaction = cur_trans;
35                 cur_trans->num_writers = 0;
36                 cur_trans->transid = root->root_key.offset + 1;
37                 init_waitqueue_head(&cur_trans->writer_wait);
38                 init_waitqueue_head(&cur_trans->commit_wait);
39                 cur_trans->magic = TRANS_MAGIC;
40                 cur_trans->in_commit = 0;
41                 cur_trans->use_count = 1;
42                 cur_trans->commit_done = 0;
43         }
44         cur_trans->num_writers++;
45         return 0;
46 }
47
48 struct btrfs_trans_handle *btrfs_start_transaction(struct btrfs_root *root,
49                                                    int num_blocks)
50 {
51         struct btrfs_trans_handle *h =
52                 kmem_cache_alloc(btrfs_trans_handle_cachep, GFP_NOFS);
53         int ret;
54
55         mutex_lock(&root->fs_info->trans_mutex);
56         ret = join_transaction(root);
57         BUG_ON(ret);
58         h->transid = root->fs_info->running_transaction->transid;
59         h->transaction = root->fs_info->running_transaction;
60         h->blocks_reserved = num_blocks;
61         h->blocks_used = 0;
62         root->fs_info->running_transaction->use_count++;
63         mutex_unlock(&root->fs_info->trans_mutex);
64         h->magic = h->magic2 = TRANS_MAGIC;
65         return h;
66 }
67
68 int btrfs_end_transaction(struct btrfs_trans_handle *trans,
69                           struct btrfs_root *root)
70 {
71         struct btrfs_transaction *cur_trans;
72         WARN_ON(trans->magic != TRANS_MAGIC);
73         WARN_ON(trans->magic2 != TRANS_MAGIC);
74         mutex_lock(&root->fs_info->trans_mutex);
75         cur_trans = root->fs_info->running_transaction;
76         WARN_ON(cur_trans->num_writers < 1);
77         if (waitqueue_active(&cur_trans->writer_wait))
78                 wake_up(&cur_trans->writer_wait);
79         cur_trans->num_writers--;
80         put_transaction(cur_trans);
81         mutex_unlock(&root->fs_info->trans_mutex);
82         memset(trans, 0, sizeof(*trans));
83         kmem_cache_free(btrfs_trans_handle_cachep, trans);
84         return 0;
85 }
86
87
88 int btrfs_write_and_wait_transaction(struct btrfs_trans_handle *trans,
89                                      struct btrfs_root *root)
90 {
91         filemap_write_and_wait(root->fs_info->sb->s_bdev->bd_inode->i_mapping);
92         return 0;
93 }
94
95 int btrfs_commit_tree_roots(struct btrfs_trans_handle *trans,
96                             struct btrfs_root *root)
97 {
98         int ret;
99         u64 old_extent_block;
100         struct btrfs_fs_info *fs_info = root->fs_info;
101         struct btrfs_root *tree_root = fs_info->tree_root;
102         struct btrfs_root *extent_root = fs_info->extent_root;
103         struct btrfs_root *inode_root = fs_info->inode_root;
104
105         btrfs_set_root_blocknr(&inode_root->root_item,
106                                inode_root->node->b_blocknr);
107         ret = btrfs_update_root(trans, tree_root,
108                                 &inode_root->root_key,
109                                 &inode_root->root_item);
110         BUG_ON(ret);
111         while(1) {
112                 old_extent_block = btrfs_root_blocknr(&extent_root->root_item);
113                 if (old_extent_block == extent_root->node->b_blocknr)
114                         break;
115                 btrfs_set_root_blocknr(&extent_root->root_item,
116                                        extent_root->node->b_blocknr);
117                 ret = btrfs_update_root(trans, tree_root,
118                                         &extent_root->root_key,
119                                         &extent_root->root_item);
120                 BUG_ON(ret);
121         }
122         return 0;
123 }
124
125 static int wait_for_commit(struct btrfs_root *root,
126                            struct btrfs_transaction *commit)
127 {
128         DEFINE_WAIT(wait);
129         while(!commit->commit_done) {
130                 prepare_to_wait(&commit->commit_wait, &wait,
131                                 TASK_UNINTERRUPTIBLE);
132                 if (commit->commit_done)
133                         break;
134                 mutex_unlock(&root->fs_info->trans_mutex);
135                 schedule();
136                 mutex_lock(&root->fs_info->trans_mutex);
137         }
138         finish_wait(&commit->commit_wait, &wait);
139         return 0;
140 }
141
142 int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
143                              struct btrfs_root *root)
144 {
145         int ret = 0;
146         struct buffer_head *snap;
147         struct btrfs_key snap_key;
148         struct btrfs_transaction *cur_trans;
149         DEFINE_WAIT(wait);
150
151         mutex_lock(&root->fs_info->trans_mutex);
152         if (trans->transaction->in_commit) {
153 printk("already in commit!, waiting\n");
154                 cur_trans = trans->transaction;
155                 trans->transaction->use_count++;
156                 btrfs_end_transaction(trans, root);
157                 ret = wait_for_commit(root, cur_trans);
158                 BUG_ON(ret);
159                 put_transaction(cur_trans);
160                 mutex_unlock(&root->fs_info->trans_mutex);
161                 return 0;
162         }
163         cur_trans = trans->transaction;
164         trans->transaction->in_commit = 1;
165         while (trans->transaction->num_writers > 1) {
166                 WARN_ON(cur_trans != trans->transaction);
167                 prepare_to_wait(&trans->transaction->writer_wait, &wait,
168                                 TASK_UNINTERRUPTIBLE);
169                 if (trans->transaction->num_writers <= 1)
170                         break;
171                 mutex_unlock(&root->fs_info->trans_mutex);
172                 schedule();
173                 mutex_lock(&root->fs_info->trans_mutex);
174                 finish_wait(&trans->transaction->writer_wait, &wait);
175         }
176         finish_wait(&trans->transaction->writer_wait, &wait);
177         WARN_ON(cur_trans != trans->transaction);
178         if (root->node != root->commit_root) {
179                 memcpy(&snap_key, &root->root_key, sizeof(snap_key));
180                 root->root_key.offset++;
181         }
182
183         if (btrfs_root_blocknr(&root->root_item) != root->node->b_blocknr) {
184                 btrfs_set_root_blocknr(&root->root_item, root->node->b_blocknr);
185                 ret = btrfs_insert_root(trans, root->fs_info->tree_root,
186                                         &root->root_key, &root->root_item);
187                 BUG_ON(ret);
188         }
189
190         ret = btrfs_commit_tree_roots(trans, root);
191         BUG_ON(ret);
192         cur_trans = root->fs_info->running_transaction;
193         root->fs_info->running_transaction = NULL;
194         mutex_unlock(&root->fs_info->trans_mutex);
195         ret = btrfs_write_and_wait_transaction(trans, root);
196         BUG_ON(ret);
197
198         write_ctree_super(trans, root);
199         btrfs_finish_extent_commit(trans, root);
200         mutex_lock(&root->fs_info->trans_mutex);
201         cur_trans->commit_done = 1;
202         wake_up(&cur_trans->commit_wait);
203         put_transaction(cur_trans);
204         put_transaction(cur_trans);
205         mutex_unlock(&root->fs_info->trans_mutex);
206         kmem_cache_free(btrfs_trans_handle_cachep, trans);
207         if (root->node != root->commit_root) {
208                 trans = btrfs_start_transaction(root, 1);
209                 snap = root->commit_root;
210                 root->commit_root = root->node;
211                 get_bh(root->node);
212                 ret = btrfs_drop_snapshot(trans, root, snap);
213                 BUG_ON(ret);
214
215                 ret = btrfs_del_root(trans, root->fs_info->tree_root,
216                                      &snap_key);
217                 BUG_ON(ret);
218                 root->fs_info->generation = root->root_key.offset + 1;
219                 ret = btrfs_end_transaction(trans, root);
220                 BUG_ON(ret);
221         }
222         return ret;
223 }
224