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