diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-03-22 12:13:20 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@hera.kernel.org> | 2007-03-22 12:13:20 -0400 |
commit | e20d96d64f9cf9288ffecc9ad4714e91c3b97ca8 (patch) | |
tree | fbe07d48bc7997226075169118ffa2a2e63f5d51 /fs/btrfs/disk-io.c | |
parent | 2e635a278354a1a7951e16cfea4c247d6d0e7c99 (diff) |
Mountable btrfs, with readdir
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/disk-io.c')
-rw-r--r-- | fs/btrfs/disk-io.c | 281 |
1 files changed, 83 insertions, 198 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 05637f9fd7c7..df2061a735cd 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -1,165 +1,67 @@ | |||
1 | #define _XOPEN_SOURCE 500 | 1 | #include <linux/module.h> |
2 | #include <stdio.h> | 2 | #include <linux/fs.h> |
3 | #include <stdlib.h> | ||
4 | #include <sys/types.h> | ||
5 | #include <sys/stat.h> | ||
6 | #include <fcntl.h> | ||
7 | #include <unistd.h> | ||
8 | #include "kerncompat.h" | ||
9 | #include "radix-tree.h" | ||
10 | #include "ctree.h" | 3 | #include "ctree.h" |
11 | #include "disk-io.h" | 4 | #include "disk-io.h" |
12 | #include "transaction.h" | 5 | #include "transaction.h" |
13 | 6 | ||
14 | static int allocated_blocks = 0; | 7 | static int check_tree_block(struct btrfs_root *root, struct buffer_head *buf) |
15 | int cache_max = 10000; | ||
16 | |||
17 | static int check_tree_block(struct btrfs_root *root, struct btrfs_buffer *buf) | ||
18 | { | 8 | { |
19 | if (buf->blocknr != btrfs_header_blocknr(&buf->node.header)) | 9 | struct btrfs_node *node = btrfs_buffer_node(buf); |
10 | if (buf->b_blocknr != btrfs_header_blocknr(&node->header)) | ||
20 | BUG(); | 11 | BUG(); |
21 | if (root->node && btrfs_header_parentid(&buf->node.header) != | 12 | if (root->node && btrfs_header_parentid(&node->header) != |
22 | btrfs_header_parentid(&root->node->node.header)) | 13 | btrfs_header_parentid(btrfs_buffer_header(root->node))) |
23 | BUG(); | 14 | BUG(); |
24 | return 0; | 15 | return 0; |
25 | } | 16 | } |
26 | 17 | ||
27 | static int free_some_buffers(struct btrfs_root *root) | 18 | struct buffer_head *alloc_tree_block(struct btrfs_root *root, u64 blocknr) |
28 | { | 19 | { |
29 | struct list_head *node, *next; | 20 | return sb_getblk(root->fs_info->sb, blocknr); |
30 | struct btrfs_buffer *b; | ||
31 | if (root->fs_info->cache_size < cache_max) | ||
32 | return 0; | ||
33 | list_for_each_safe(node, next, &root->fs_info->cache) { | ||
34 | b = list_entry(node, struct btrfs_buffer, cache); | ||
35 | if (b->count == 1) { | ||
36 | BUG_ON(!list_empty(&b->dirty)); | ||
37 | list_del_init(&b->cache); | ||
38 | btrfs_block_release(root, b); | ||
39 | if (root->fs_info->cache_size < cache_max) | ||
40 | break; | ||
41 | } | ||
42 | } | ||
43 | return 0; | ||
44 | } | 21 | } |
45 | 22 | ||
46 | struct btrfs_buffer *alloc_tree_block(struct btrfs_root *root, u64 blocknr) | 23 | struct buffer_head *find_tree_block(struct btrfs_root *root, u64 blocknr) |
47 | { | 24 | { |
48 | struct btrfs_buffer *buf; | 25 | return sb_getblk(root->fs_info->sb, blocknr); |
49 | int ret; | ||
50 | |||
51 | buf = malloc(sizeof(struct btrfs_buffer) + root->blocksize); | ||
52 | if (!buf) | ||
53 | return buf; | ||
54 | allocated_blocks++; | ||
55 | buf->blocknr = blocknr; | ||
56 | buf->count = 2; | ||
57 | INIT_LIST_HEAD(&buf->dirty); | ||
58 | free_some_buffers(root); | ||
59 | radix_tree_preload(GFP_KERNEL); | ||
60 | ret = radix_tree_insert(&root->fs_info->cache_radix, blocknr, buf); | ||
61 | radix_tree_preload_end(); | ||
62 | list_add_tail(&buf->cache, &root->fs_info->cache); | ||
63 | root->fs_info->cache_size++; | ||
64 | if (ret) { | ||
65 | free(buf); | ||
66 | return NULL; | ||
67 | } | ||
68 | return buf; | ||
69 | } | 26 | } |
70 | 27 | ||
71 | struct btrfs_buffer *find_tree_block(struct btrfs_root *root, u64 blocknr) | 28 | struct buffer_head *read_tree_block(struct btrfs_root *root, u64 blocknr) |
72 | { | 29 | { |
73 | struct btrfs_buffer *buf; | 30 | struct buffer_head *buf = sb_bread(root->fs_info->sb, blocknr); |
74 | buf = radix_tree_lookup(&root->fs_info->cache_radix, blocknr); | ||
75 | if (buf) { | ||
76 | buf->count++; | ||
77 | } else { | ||
78 | buf = alloc_tree_block(root, blocknr); | ||
79 | if (!buf) { | ||
80 | BUG(); | ||
81 | return NULL; | ||
82 | } | ||
83 | } | ||
84 | return buf; | ||
85 | } | ||
86 | |||
87 | struct btrfs_buffer *read_tree_block(struct btrfs_root *root, u64 blocknr) | ||
88 | { | ||
89 | loff_t offset = blocknr * root->blocksize; | ||
90 | struct btrfs_buffer *buf; | ||
91 | int ret; | ||
92 | 31 | ||
93 | buf = radix_tree_lookup(&root->fs_info->cache_radix, blocknr); | 32 | if (!buf) |
94 | if (buf) { | 33 | return buf; |
95 | buf->count++; | ||
96 | } else { | ||
97 | buf = alloc_tree_block(root, blocknr); | ||
98 | if (!buf) | ||
99 | return NULL; | ||
100 | ret = pread(root->fs_info->fp, &buf->node, root->blocksize, | ||
101 | offset); | ||
102 | if (ret != root->blocksize) { | ||
103 | free(buf); | ||
104 | return NULL; | ||
105 | } | ||
106 | } | ||
107 | if (check_tree_block(root, buf)) | 34 | if (check_tree_block(root, buf)) |
108 | BUG(); | 35 | BUG(); |
109 | return buf; | 36 | return buf; |
110 | } | 37 | } |
111 | 38 | ||
112 | int dirty_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 39 | int dirty_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
113 | struct btrfs_buffer *buf) | 40 | struct buffer_head *buf) |
114 | { | 41 | { |
115 | if (!list_empty(&buf->dirty)) | 42 | mark_buffer_dirty(buf); |
116 | return 0; | ||
117 | list_add_tail(&buf->dirty, &root->fs_info->trans); | ||
118 | buf->count++; | ||
119 | return 0; | 43 | return 0; |
120 | } | 44 | } |
121 | 45 | ||
122 | int clean_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 46 | int clean_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
123 | struct btrfs_buffer *buf) | 47 | struct buffer_head *buf) |
124 | { | 48 | { |
125 | if (!list_empty(&buf->dirty)) { | 49 | clear_buffer_dirty(buf); |
126 | list_del_init(&buf->dirty); | ||
127 | btrfs_block_release(root, buf); | ||
128 | } | ||
129 | return 0; | 50 | return 0; |
130 | } | 51 | } |
131 | 52 | ||
132 | int write_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 53 | int write_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
133 | struct btrfs_buffer *buf) | 54 | struct buffer_head *buf) |
134 | { | 55 | { |
135 | u64 blocknr = buf->blocknr; | 56 | mark_buffer_dirty(buf); |
136 | loff_t offset = blocknr * root->blocksize; | ||
137 | int ret; | ||
138 | |||
139 | if (buf->blocknr != btrfs_header_blocknr(&buf->node.header)) | ||
140 | BUG(); | ||
141 | ret = pwrite(root->fs_info->fp, &buf->node, root->blocksize, offset); | ||
142 | if (ret != root->blocksize) | ||
143 | return ret; | ||
144 | return 0; | 57 | return 0; |
145 | } | 58 | } |
146 | 59 | ||
147 | static int __commit_transaction(struct btrfs_trans_handle *trans, struct | 60 | static int __commit_transaction(struct btrfs_trans_handle *trans, struct |
148 | btrfs_root *root) | 61 | btrfs_root *root) |
149 | { | 62 | { |
150 | struct btrfs_buffer *b; | 63 | filemap_write_and_wait(root->fs_info->sb->s_bdev->bd_inode->i_mapping); |
151 | int ret = 0; | 64 | return 0; |
152 | int wret; | ||
153 | while(!list_empty(&root->fs_info->trans)) { | ||
154 | b = list_entry(root->fs_info->trans.next, struct btrfs_buffer, | ||
155 | dirty); | ||
156 | list_del_init(&b->dirty); | ||
157 | wret = write_tree_block(trans, root, b); | ||
158 | if (wret) | ||
159 | ret = wret; | ||
160 | btrfs_block_release(root, b); | ||
161 | } | ||
162 | return ret; | ||
163 | } | 65 | } |
164 | 66 | ||
165 | static int commit_tree_roots(struct btrfs_trans_handle *trans, | 67 | static int commit_tree_roots(struct btrfs_trans_handle *trans, |
@@ -172,17 +74,17 @@ static int commit_tree_roots(struct btrfs_trans_handle *trans, | |||
172 | struct btrfs_root *inode_root = fs_info->inode_root; | 74 | struct btrfs_root *inode_root = fs_info->inode_root; |
173 | 75 | ||
174 | btrfs_set_root_blocknr(&inode_root->root_item, | 76 | btrfs_set_root_blocknr(&inode_root->root_item, |
175 | inode_root->node->blocknr); | 77 | inode_root->node->b_blocknr); |
176 | ret = btrfs_update_root(trans, tree_root, | 78 | ret = btrfs_update_root(trans, tree_root, |
177 | &inode_root->root_key, | 79 | &inode_root->root_key, |
178 | &inode_root->root_item); | 80 | &inode_root->root_item); |
179 | BUG_ON(ret); | 81 | BUG_ON(ret); |
180 | while(1) { | 82 | while(1) { |
181 | old_extent_block = btrfs_root_blocknr(&extent_root->root_item); | 83 | old_extent_block = btrfs_root_blocknr(&extent_root->root_item); |
182 | if (old_extent_block == extent_root->node->blocknr) | 84 | if (old_extent_block == extent_root->node->b_blocknr) |
183 | break; | 85 | break; |
184 | btrfs_set_root_blocknr(&extent_root->root_item, | 86 | btrfs_set_root_blocknr(&extent_root->root_item, |
185 | extent_root->node->blocknr); | 87 | extent_root->node->b_blocknr); |
186 | ret = btrfs_update_root(trans, tree_root, | 88 | ret = btrfs_update_root(trans, tree_root, |
187 | &extent_root->root_key, | 89 | &extent_root->root_key, |
188 | &extent_root->root_item); | 90 | &extent_root->root_item); |
@@ -195,7 +97,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, struct | |||
195 | btrfs_root *root, struct btrfs_super_block *s) | 97 | btrfs_root *root, struct btrfs_super_block *s) |
196 | { | 98 | { |
197 | int ret = 0; | 99 | int ret = 0; |
198 | struct btrfs_buffer *snap = root->commit_root; | 100 | struct buffer_head *snap = root->commit_root; |
199 | struct btrfs_key snap_key; | 101 | struct btrfs_key snap_key; |
200 | 102 | ||
201 | if (root->commit_root == root->node) | 103 | if (root->commit_root == root->node) |
@@ -204,7 +106,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, struct | |||
204 | memcpy(&snap_key, &root->root_key, sizeof(snap_key)); | 106 | memcpy(&snap_key, &root->root_key, sizeof(snap_key)); |
205 | root->root_key.offset++; | 107 | root->root_key.offset++; |
206 | 108 | ||
207 | btrfs_set_root_blocknr(&root->root_item, root->node->blocknr); | 109 | btrfs_set_root_blocknr(&root->root_item, root->node->b_blocknr); |
208 | ret = btrfs_insert_root(trans, root->fs_info->tree_root, | 110 | ret = btrfs_insert_root(trans, root->fs_info->tree_root, |
209 | &root->root_key, &root->root_item); | 111 | &root->root_key, &root->root_item); |
210 | BUG_ON(ret); | 112 | BUG_ON(ret); |
@@ -220,7 +122,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, struct | |||
220 | btrfs_finish_extent_commit(trans, root->fs_info->tree_root); | 122 | btrfs_finish_extent_commit(trans, root->fs_info->tree_root); |
221 | 123 | ||
222 | root->commit_root = root->node; | 124 | root->commit_root = root->node; |
223 | root->node->count++; | 125 | get_bh(root->node); |
224 | ret = btrfs_drop_snapshot(trans, root, snap); | 126 | ret = btrfs_drop_snapshot(trans, root, snap); |
225 | BUG_ON(ret); | 127 | BUG_ON(ret); |
226 | 128 | ||
@@ -234,7 +136,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, struct | |||
234 | static int __setup_root(struct btrfs_super_block *super, | 136 | static int __setup_root(struct btrfs_super_block *super, |
235 | struct btrfs_root *root, | 137 | struct btrfs_root *root, |
236 | struct btrfs_fs_info *fs_info, | 138 | struct btrfs_fs_info *fs_info, |
237 | u64 objectid, int fp) | 139 | u64 objectid) |
238 | { | 140 | { |
239 | root->node = NULL; | 141 | root->node = NULL; |
240 | root->commit_root = NULL; | 142 | root->commit_root = NULL; |
@@ -250,11 +152,11 @@ static int find_and_setup_root(struct btrfs_super_block *super, | |||
250 | struct btrfs_root *tree_root, | 152 | struct btrfs_root *tree_root, |
251 | struct btrfs_fs_info *fs_info, | 153 | struct btrfs_fs_info *fs_info, |
252 | u64 objectid, | 154 | u64 objectid, |
253 | struct btrfs_root *root, int fp) | 155 | struct btrfs_root *root) |
254 | { | 156 | { |
255 | int ret; | 157 | int ret; |
256 | 158 | ||
257 | __setup_root(super, root, fs_info, objectid, fp); | 159 | __setup_root(super, root, fs_info, objectid); |
258 | ret = btrfs_find_last_root(tree_root, objectid, | 160 | ret = btrfs_find_last_root(tree_root, objectid, |
259 | &root->root_item, &root->root_key); | 161 | &root->root_item, &root->root_key); |
260 | BUG_ON(ret); | 162 | BUG_ON(ret); |
@@ -265,32 +167,26 @@ static int find_and_setup_root(struct btrfs_super_block *super, | |||
265 | return 0; | 167 | return 0; |
266 | } | 168 | } |
267 | 169 | ||
268 | struct btrfs_root *open_ctree(char *filename, struct btrfs_super_block *super) | 170 | struct btrfs_root *open_ctree(struct super_block *sb, |
171 | struct buffer_head *sb_buffer, | ||
172 | struct btrfs_super_block *disk_super) | ||
269 | { | 173 | { |
270 | int fp; | 174 | struct btrfs_root *root = kmalloc(sizeof(struct btrfs_root), |
271 | 175 | GFP_NOFS); | |
272 | fp = open(filename, O_CREAT | O_RDWR, 0600); | 176 | struct btrfs_root *extent_root = kmalloc(sizeof(struct btrfs_root), |
273 | if (fp < 0) { | 177 | GFP_NOFS); |
274 | return NULL; | 178 | struct btrfs_root *tree_root = kmalloc(sizeof(struct btrfs_root), |
275 | } | 179 | GFP_NOFS); |
276 | return open_ctree_fd(fp, super); | 180 | struct btrfs_root *inode_root = kmalloc(sizeof(struct btrfs_root), |
277 | } | 181 | GFP_NOFS); |
278 | 182 | struct btrfs_fs_info *fs_info = kmalloc(sizeof(*fs_info), | |
279 | struct btrfs_root *open_ctree_fd(int fp, struct btrfs_super_block *super) | 183 | GFP_NOFS); |
280 | { | ||
281 | struct btrfs_root *root = malloc(sizeof(struct btrfs_root)); | ||
282 | struct btrfs_root *extent_root = malloc(sizeof(struct btrfs_root)); | ||
283 | struct btrfs_root *tree_root = malloc(sizeof(struct btrfs_root)); | ||
284 | struct btrfs_root *inode_root = malloc(sizeof(struct btrfs_root)); | ||
285 | struct btrfs_fs_info *fs_info = malloc(sizeof(*fs_info)); | ||
286 | int ret; | 184 | int ret; |
287 | 185 | ||
288 | INIT_RADIX_TREE(&fs_info->cache_radix, GFP_KERNEL); | 186 | /* FIXME: don't be stupid */ |
187 | if (!btrfs_super_root(disk_super)) | ||
188 | return NULL; | ||
289 | INIT_RADIX_TREE(&fs_info->pinned_radix, GFP_KERNEL); | 189 | INIT_RADIX_TREE(&fs_info->pinned_radix, GFP_KERNEL); |
290 | INIT_LIST_HEAD(&fs_info->trans); | ||
291 | INIT_LIST_HEAD(&fs_info->cache); | ||
292 | fs_info->cache_size = 0; | ||
293 | fs_info->fp = fp; | ||
294 | fs_info->running_transaction = NULL; | 190 | fs_info->running_transaction = NULL; |
295 | fs_info->fs_root = root; | 191 | fs_info->fs_root = root; |
296 | fs_info->tree_root = tree_root; | 192 | fs_info->tree_root = tree_root; |
@@ -298,36 +194,31 @@ struct btrfs_root *open_ctree_fd(int fp, struct btrfs_super_block *super) | |||
298 | fs_info->inode_root = inode_root; | 194 | fs_info->inode_root = inode_root; |
299 | fs_info->last_inode_alloc = 0; | 195 | fs_info->last_inode_alloc = 0; |
300 | fs_info->last_inode_alloc_dirid = 0; | 196 | fs_info->last_inode_alloc_dirid = 0; |
301 | fs_info->disk_super = super; | 197 | fs_info->disk_super = disk_super; |
198 | fs_info->sb_buffer = sb_buffer; | ||
199 | fs_info->sb = sb; | ||
302 | memset(&fs_info->current_insert, 0, sizeof(fs_info->current_insert)); | 200 | memset(&fs_info->current_insert, 0, sizeof(fs_info->current_insert)); |
303 | memset(&fs_info->last_insert, 0, sizeof(fs_info->last_insert)); | 201 | memset(&fs_info->last_insert, 0, sizeof(fs_info->last_insert)); |
304 | 202 | ||
305 | ret = pread(fp, super, sizeof(struct btrfs_super_block), | 203 | __setup_root(disk_super, tree_root, fs_info, BTRFS_ROOT_TREE_OBJECTID); |
306 | BTRFS_SUPER_INFO_OFFSET); | 204 | tree_root->node = read_tree_block(tree_root, |
307 | if (ret == 0 || btrfs_super_root(super) == 0) { | 205 | btrfs_super_root(disk_super)); |
308 | BUG(); | ||
309 | return NULL; | ||
310 | } | ||
311 | BUG_ON(ret < 0); | ||
312 | |||
313 | __setup_root(super, tree_root, fs_info, BTRFS_ROOT_TREE_OBJECTID, fp); | ||
314 | tree_root->node = read_tree_block(tree_root, btrfs_super_root(super)); | ||
315 | BUG_ON(!tree_root->node); | 206 | BUG_ON(!tree_root->node); |
316 | 207 | ||
317 | ret = find_and_setup_root(super, tree_root, fs_info, | 208 | ret = find_and_setup_root(disk_super, tree_root, fs_info, |
318 | BTRFS_EXTENT_TREE_OBJECTID, extent_root, fp); | 209 | BTRFS_EXTENT_TREE_OBJECTID, extent_root); |
319 | BUG_ON(ret); | 210 | BUG_ON(ret); |
320 | 211 | ||
321 | ret = find_and_setup_root(super, tree_root, fs_info, | 212 | ret = find_and_setup_root(disk_super, tree_root, fs_info, |
322 | BTRFS_INODE_MAP_OBJECTID, inode_root, fp); | 213 | BTRFS_INODE_MAP_OBJECTID, inode_root); |
323 | BUG_ON(ret); | 214 | BUG_ON(ret); |
324 | 215 | ||
325 | ret = find_and_setup_root(super, tree_root, fs_info, | 216 | ret = find_and_setup_root(disk_super, tree_root, fs_info, |
326 | BTRFS_FS_TREE_OBJECTID, root, fp); | 217 | BTRFS_FS_TREE_OBJECTID, root); |
327 | BUG_ON(ret); | 218 | BUG_ON(ret); |
328 | 219 | ||
329 | root->commit_root = root->node; | 220 | root->commit_root = root->node; |
330 | root->node->count++; | 221 | get_bh(root->node); |
331 | root->ref_cows = 1; | 222 | root->ref_cows = 1; |
332 | root->fs_info->generation = root->root_key.offset + 1; | 223 | root->fs_info->generation = root->root_key.offset + 1; |
333 | return root; | 224 | return root; |
@@ -336,8 +227,11 @@ struct btrfs_root *open_ctree_fd(int fp, struct btrfs_super_block *super) | |||
336 | int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root | 227 | int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root |
337 | *root, struct btrfs_super_block *s) | 228 | *root, struct btrfs_super_block *s) |
338 | { | 229 | { |
230 | return 0; | ||
231 | #if 0 | ||
339 | int ret; | 232 | int ret; |
340 | btrfs_set_super_root(s, root->fs_info->tree_root->node->blocknr); | 233 | btrfs_set_super_root(s, root->fs_info->tree_root->node->b_blocknr); |
234 | |||
341 | ret = pwrite(root->fs_info->fp, s, sizeof(*s), | 235 | ret = pwrite(root->fs_info->fp, s, sizeof(*s), |
342 | BTRFS_SUPER_INFO_OFFSET); | 236 | BTRFS_SUPER_INFO_OFFSET); |
343 | if (ret != sizeof(*s)) { | 237 | if (ret != sizeof(*s)) { |
@@ -345,35 +239,38 @@ int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root | |||
345 | return ret; | 239 | return ret; |
346 | } | 240 | } |
347 | return 0; | 241 | return 0; |
242 | #endif | ||
348 | } | 243 | } |
349 | 244 | ||
350 | static int drop_cache(struct btrfs_root *root) | 245 | static int drop_cache(struct btrfs_root *root) |
351 | { | 246 | { |
247 | return 0; | ||
248 | #if 0 | ||
352 | while(!list_empty(&root->fs_info->cache)) { | 249 | while(!list_empty(&root->fs_info->cache)) { |
353 | struct btrfs_buffer *b = list_entry(root->fs_info->cache.next, | 250 | struct buffer_head *b = list_entry(root->fs_info->cache.next, |
354 | struct btrfs_buffer, | 251 | struct buffer_head, |
355 | cache); | 252 | cache); |
356 | list_del_init(&b->cache); | 253 | list_del_init(&b->cache); |
357 | btrfs_block_release(root, b); | 254 | btrfs_block_release(root, b); |
358 | } | 255 | } |
359 | return 0; | 256 | return 0; |
257 | #endif | ||
360 | } | 258 | } |
361 | int close_ctree(struct btrfs_root *root, struct btrfs_super_block *s) | 259 | |
260 | int close_ctree(struct btrfs_root *root) | ||
362 | { | 261 | { |
363 | int ret; | 262 | int ret; |
364 | struct btrfs_trans_handle *trans; | 263 | struct btrfs_trans_handle *trans; |
365 | 264 | ||
366 | trans = root->fs_info->running_transaction; | 265 | trans = root->fs_info->running_transaction; |
367 | btrfs_commit_transaction(trans, root, s); | 266 | btrfs_commit_transaction(trans, root, root->fs_info->disk_super); |
368 | ret = commit_tree_roots(trans, root->fs_info); | 267 | ret = commit_tree_roots(trans, root->fs_info); |
369 | BUG_ON(ret); | 268 | BUG_ON(ret); |
370 | ret = __commit_transaction(trans, root); | 269 | ret = __commit_transaction(trans, root); |
371 | BUG_ON(ret); | 270 | BUG_ON(ret); |
372 | write_ctree_super(trans, root, s); | 271 | write_ctree_super(trans, root, root->fs_info->disk_super); |
373 | drop_cache(root); | 272 | drop_cache(root); |
374 | BUG_ON(!list_empty(&root->fs_info->trans)); | ||
375 | 273 | ||
376 | close(root->fs_info->fp); | ||
377 | if (root->node) | 274 | if (root->node) |
378 | btrfs_block_release(root, root->node); | 275 | btrfs_block_release(root, root->node); |
379 | if (root->fs_info->extent_root->node) | 276 | if (root->fs_info->extent_root->node) |
@@ -386,29 +283,17 @@ int close_ctree(struct btrfs_root *root, struct btrfs_super_block *s) | |||
386 | btrfs_block_release(root->fs_info->tree_root, | 283 | btrfs_block_release(root->fs_info->tree_root, |
387 | root->fs_info->tree_root->node); | 284 | root->fs_info->tree_root->node); |
388 | btrfs_block_release(root, root->commit_root); | 285 | btrfs_block_release(root, root->commit_root); |
389 | free(root); | 286 | btrfs_block_release(root, root->fs_info->sb_buffer); |
390 | printf("on close %d blocks are allocated\n", allocated_blocks); | 287 | kfree(root->fs_info->extent_root); |
288 | kfree(root->fs_info->inode_root); | ||
289 | kfree(root->fs_info->tree_root); | ||
290 | kfree(root->fs_info); | ||
291 | kfree(root); | ||
391 | return 0; | 292 | return 0; |
392 | } | 293 | } |
393 | 294 | ||
394 | void btrfs_block_release(struct btrfs_root *root, struct btrfs_buffer *buf) | 295 | void btrfs_block_release(struct btrfs_root *root, struct buffer_head *buf) |
395 | { | 296 | { |
396 | buf->count--; | 297 | brelse(buf); |
397 | if (buf->count < 0) | ||
398 | BUG(); | ||
399 | if (buf->count == 0) { | ||
400 | BUG_ON(!list_empty(&buf->cache)); | ||
401 | BUG_ON(!list_empty(&buf->dirty)); | ||
402 | if (!radix_tree_lookup(&root->fs_info->cache_radix, | ||
403 | buf->blocknr)) | ||
404 | BUG(); | ||
405 | radix_tree_delete(&root->fs_info->cache_radix, buf->blocknr); | ||
406 | memset(buf, 0, sizeof(*buf)); | ||
407 | free(buf); | ||
408 | BUG_ON(allocated_blocks == 0); | ||
409 | allocated_blocks--; | ||
410 | BUG_ON(root->fs_info->cache_size == 0); | ||
411 | root->fs_info->cache_size--; | ||
412 | } | ||
413 | } | 298 | } |
414 | 299 | ||