]> git.karo-electronics.de Git - karo-tx-linux.git/blob - fs/btrfs/transaction.c
Btrfs: start of support for many FS volumes
[karo-tx-linux.git] / 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         /* FIXME, use the right root */
56         root = root->fs_info->fs_root;
57         mutex_lock(&root->fs_info->trans_mutex);
58         ret = join_transaction(root);
59         BUG_ON(ret);
60         h->transid = root->fs_info->running_transaction->transid;
61         h->transaction = root->fs_info->running_transaction;
62         h->blocks_reserved = num_blocks;
63         h->blocks_used = 0;
64         root->fs_info->running_transaction->use_count++;
65         mutex_unlock(&root->fs_info->trans_mutex);
66         h->magic = h->magic2 = TRANS_MAGIC;
67         return h;
68 }
69
70 int btrfs_end_transaction(struct btrfs_trans_handle *trans,
71                           struct btrfs_root *root)
72 {
73         struct btrfs_transaction *cur_trans;
74
75         /* FIXME, use the right root */
76         root = root->fs_info->fs_root;
77
78         WARN_ON(trans->magic != TRANS_MAGIC);
79         WARN_ON(trans->magic2 != TRANS_MAGIC);
80         mutex_lock(&root->fs_info->trans_mutex);
81         cur_trans = root->fs_info->running_transaction;
82         WARN_ON(cur_trans->num_writers < 1);
83         if (waitqueue_active(&cur_trans->writer_wait))
84                 wake_up(&cur_trans->writer_wait);
85         cur_trans->num_writers--;
86         put_transaction(cur_trans);
87         mutex_unlock(&root->fs_info->trans_mutex);
88         memset(trans, 0, sizeof(*trans));
89         kmem_cache_free(btrfs_trans_handle_cachep, trans);
90         return 0;
91 }
92
93
94 int btrfs_write_and_wait_transaction(struct btrfs_trans_handle *trans,
95                                      struct btrfs_root *root)
96 {
97         filemap_write_and_wait(root->fs_info->btree_inode->i_mapping);
98         return 0;
99 }
100
101 int btrfs_commit_tree_roots(struct btrfs_trans_handle *trans,
102                             struct btrfs_root *root)
103 {
104         int ret;
105         u64 old_extent_block;
106         struct btrfs_fs_info *fs_info = root->fs_info;
107         struct btrfs_root *tree_root = fs_info->tree_root;
108         struct btrfs_root *extent_root = fs_info->extent_root;
109         struct btrfs_root *inode_root = fs_info->inode_root;
110
111         btrfs_set_root_blocknr(&inode_root->root_item,
112                                inode_root->node->b_blocknr);
113         ret = btrfs_update_root(trans, tree_root,
114                                 &inode_root->root_key,
115                                 &inode_root->root_item);
116         BUG_ON(ret);
117         while(1) {
118                 old_extent_block = btrfs_root_blocknr(&extent_root->root_item);
119                 if (old_extent_block == extent_root->node->b_blocknr)
120                         break;
121                 btrfs_set_root_blocknr(&extent_root->root_item,
122                                        extent_root->node->b_blocknr);
123                 ret = btrfs_update_root(trans, tree_root,
124                                         &extent_root->root_key,
125                                         &extent_root->root_item);
126                 BUG_ON(ret);
127         }
128         return 0;
129 }
130
131 static int wait_for_commit(struct btrfs_root *root,
132                            struct btrfs_transaction *commit)
133 {
134         DEFINE_WAIT(wait);
135         while(!commit->commit_done) {
136                 prepare_to_wait(&commit->commit_wait, &wait,
137                                 TASK_UNINTERRUPTIBLE);
138                 if (commit->commit_done)
139                         break;
140                 mutex_unlock(&root->fs_info->trans_mutex);
141                 schedule();
142                 mutex_lock(&root->fs_info->trans_mutex);
143         }
144         finish_wait(&commit->commit_wait, &wait);
145         return 0;
146 }
147
148 int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
149                              struct btrfs_root *root)
150 {
151         int ret = 0;
152         struct buffer_head *snap;
153         struct btrfs_key snap_key;
154         struct btrfs_transaction *cur_trans;
155         DEFINE_WAIT(wait);
156
157         /* FIXME, use the right root */
158         root = root->fs_info->fs_root;
159
160         mutex_lock(&root->fs_info->trans_mutex);
161         if (trans->transaction->in_commit) {
162 printk("already in commit!, waiting\n");
163                 cur_trans = trans->transaction;
164                 trans->transaction->use_count++;
165                 btrfs_end_transaction(trans, root);
166                 ret = wait_for_commit(root, cur_trans);
167                 BUG_ON(ret);
168                 put_transaction(cur_trans);
169                 mutex_unlock(&root->fs_info->trans_mutex);
170                 return 0;
171         }
172         cur_trans = trans->transaction;
173         trans->transaction->in_commit = 1;
174         while (trans->transaction->num_writers > 1) {
175                 WARN_ON(cur_trans != trans->transaction);
176                 prepare_to_wait(&trans->transaction->writer_wait, &wait,
177                                 TASK_UNINTERRUPTIBLE);
178                 if (trans->transaction->num_writers <= 1)
179                         break;
180                 mutex_unlock(&root->fs_info->trans_mutex);
181                 schedule();
182                 mutex_lock(&root->fs_info->trans_mutex);
183                 finish_wait(&trans->transaction->writer_wait, &wait);
184         }
185         finish_wait(&trans->transaction->writer_wait, &wait);
186         WARN_ON(cur_trans != trans->transaction);
187         if (root->node != root->commit_root) {
188                 memcpy(&snap_key, &root->root_key, sizeof(snap_key));
189                 root->root_key.offset++;
190         }
191
192         if (btrfs_root_blocknr(&root->root_item) != root->node->b_blocknr) {
193                 btrfs_set_root_blocknr(&root->root_item, root->node->b_blocknr);
194                 ret = btrfs_insert_root(trans, root->fs_info->tree_root,
195                                         &root->root_key, &root->root_item);
196                 BUG_ON(ret);
197         }
198
199         ret = btrfs_commit_tree_roots(trans, root);
200         BUG_ON(ret);
201         cur_trans = root->fs_info->running_transaction;
202         root->fs_info->running_transaction = NULL;
203         mutex_unlock(&root->fs_info->trans_mutex);
204         ret = btrfs_write_and_wait_transaction(trans, root);
205         BUG_ON(ret);
206
207         write_ctree_super(trans, root);
208         btrfs_finish_extent_commit(trans, root);
209         mutex_lock(&root->fs_info->trans_mutex);
210         cur_trans->commit_done = 1;
211         wake_up(&cur_trans->commit_wait);
212         put_transaction(cur_trans);
213         put_transaction(cur_trans);
214         mutex_unlock(&root->fs_info->trans_mutex);
215         kmem_cache_free(btrfs_trans_handle_cachep, trans);
216         if (root->node != root->commit_root) {
217                 trans = btrfs_start_transaction(root, 1);
218                 snap = root->commit_root;
219                 root->commit_root = root->node;
220                 get_bh(root->node);
221                 ret = btrfs_drop_snapshot(trans, root, snap);
222                 BUG_ON(ret);
223
224                 ret = btrfs_del_root(trans, root->fs_info->tree_root,
225                                      &snap_key);
226                 BUG_ON(ret);
227                 root->fs_info->generation = root->root_key.offset + 1;
228                 ret = btrfs_end_transaction(trans, root);
229                 BUG_ON(ret);
230         }
231         return ret;
232 }
233