2 * Copyright (C) 2007 Oracle. All rights reserved.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License v2 as published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public
14 * License along with this program; if not, write to the
15 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16 * Boston, MA 021110-1307, USA.
19 #define _XOPEN_SOURCE 600
23 #include <sys/types.h>
27 #include "kerncompat.h"
28 #include "radix-tree.h"
31 #include "transaction.h"
33 static int allocated_blocks
= 0;
34 int cache_max
= 10000;
36 int btrfs_map_bh_to_logical(struct btrfs_root
*root
, struct btrfs_buffer
*bh
,
39 bh
->fd
= root
->fs_info
->fp
;
40 bh
->dev_blocknr
= logical
;
44 static int check_tree_block(struct btrfs_root
*root
, struct btrfs_buffer
*buf
)
46 if (buf
->blocknr
!= btrfs_header_blocknr(&buf
->node
.header
))
48 if (memcmp(root
->fs_info
->disk_super
->fsid
, buf
->node
.header
.fsid
,
49 sizeof(buf
->node
.header
.fsid
)))
54 static int free_some_buffers(struct btrfs_root
*root
)
56 struct list_head
*node
, *next
;
57 struct btrfs_buffer
*b
;
58 if (root
->fs_info
->cache_size
< cache_max
)
60 list_for_each_safe(node
, next
, &root
->fs_info
->cache
) {
61 b
= list_entry(node
, struct btrfs_buffer
, cache
);
63 BUG_ON(!list_empty(&b
->dirty
));
64 list_del_init(&b
->cache
);
65 btrfs_block_release(root
, b
);
66 if (root
->fs_info
->cache_size
< cache_max
)
73 struct btrfs_buffer
*alloc_tree_block(struct btrfs_root
*root
, u64 blocknr
)
75 struct btrfs_buffer
*buf
;
78 buf
= malloc(sizeof(struct btrfs_buffer
) + root
->blocksize
);
82 buf
->blocknr
= blocknr
;
84 INIT_LIST_HEAD(&buf
->dirty
);
85 free_some_buffers(root
);
86 radix_tree_preload(GFP_KERNEL
);
87 ret
= radix_tree_insert(&root
->fs_info
->cache_radix
, blocknr
, buf
);
88 radix_tree_preload_end();
89 list_add_tail(&buf
->cache
, &root
->fs_info
->cache
);
90 root
->fs_info
->cache_size
++;
98 struct btrfs_buffer
*find_tree_block(struct btrfs_root
*root
, u64 blocknr
)
100 struct btrfs_buffer
*buf
;
101 buf
= radix_tree_lookup(&root
->fs_info
->cache_radix
, blocknr
);
105 buf
= alloc_tree_block(root
, blocknr
);
114 struct btrfs_buffer
*read_tree_block(struct btrfs_root
*root
, u64 blocknr
)
116 struct btrfs_buffer
*buf
;
118 buf
= radix_tree_lookup(&root
->fs_info
->cache_radix
, blocknr
);
121 if (check_tree_block(root
, buf
))
124 buf
= alloc_tree_block(root
, blocknr
);
127 btrfs_map_bh_to_logical(root
, buf
, blocknr
);
128 ret
= pread(buf
->fd
, &buf
->node
, root
->blocksize
,
129 buf
->dev_blocknr
* root
->blocksize
);
130 if (ret
!= root
->blocksize
) {
134 if (check_tree_block(root
, buf
))
140 int dirty_tree_block(struct btrfs_trans_handle
*trans
, struct btrfs_root
*root
,
141 struct btrfs_buffer
*buf
)
143 if (!list_empty(&buf
->dirty
))
145 list_add_tail(&buf
->dirty
, &root
->fs_info
->trans
);
147 if (check_tree_block(root
, buf
))
152 int clean_tree_block(struct btrfs_trans_handle
*trans
, struct btrfs_root
*root
,
153 struct btrfs_buffer
*buf
)
155 if (!list_empty(&buf
->dirty
)) {
156 list_del_init(&buf
->dirty
);
157 btrfs_block_release(root
, buf
);
162 int write_tree_block(struct btrfs_trans_handle
*trans
, struct btrfs_root
*root
,
163 struct btrfs_buffer
*buf
)
167 if (buf
->blocknr
!= btrfs_header_blocknr(&buf
->node
.header
))
169 btrfs_map_bh_to_logical(root
, buf
, buf
->blocknr
);
170 if (check_tree_block(root
, buf
))
172 ret
= pwrite(buf
->fd
, &buf
->node
, root
->blocksize
,
173 buf
->dev_blocknr
* root
->blocksize
);
174 if (ret
!= root
->blocksize
)
179 static int __commit_transaction(struct btrfs_trans_handle
*trans
, struct
182 struct btrfs_buffer
*b
;
185 while(!list_empty(&root
->fs_info
->trans
)) {
186 b
= list_entry(root
->fs_info
->trans
.next
, struct btrfs_buffer
,
188 list_del_init(&b
->dirty
);
189 wret
= write_tree_block(trans
, root
, b
);
192 btrfs_block_release(root
, b
);
197 static int commit_tree_roots(struct btrfs_trans_handle
*trans
,
198 struct btrfs_fs_info
*fs_info
)
201 u64 old_extent_block
;
202 struct btrfs_root
*tree_root
= fs_info
->tree_root
;
203 struct btrfs_root
*extent_root
= fs_info
->extent_root
;
205 btrfs_write_dirty_block_groups(trans
, fs_info
->extent_root
);
207 old_extent_block
= btrfs_root_blocknr(&extent_root
->root_item
);
208 if (old_extent_block
== extent_root
->node
->blocknr
)
210 btrfs_set_root_blocknr(&extent_root
->root_item
,
211 extent_root
->node
->blocknr
);
212 ret
= btrfs_update_root(trans
, tree_root
,
213 &extent_root
->root_key
,
214 &extent_root
->root_item
);
216 btrfs_write_dirty_block_groups(trans
, fs_info
->extent_root
);
221 int btrfs_commit_transaction(struct btrfs_trans_handle
*trans
, struct
222 btrfs_root
*root
, struct btrfs_super_block
*s
)
225 struct btrfs_buffer
*snap
= root
->commit_root
;
226 struct btrfs_key snap_key
;
228 if (root
->commit_root
== root
->node
)
231 memcpy(&snap_key
, &root
->root_key
, sizeof(snap_key
));
232 root
->root_key
.offset
++;
234 btrfs_set_root_blocknr(&root
->root_item
, root
->node
->blocknr
);
235 ret
= btrfs_insert_root(trans
, root
->fs_info
->tree_root
,
236 &root
->root_key
, &root
->root_item
);
239 ret
= commit_tree_roots(trans
, root
->fs_info
);
242 ret
= __commit_transaction(trans
, root
);
245 write_ctree_super(trans
, root
, s
);
246 btrfs_finish_extent_commit(trans
, root
->fs_info
->extent_root
);
247 btrfs_finish_extent_commit(trans
, root
->fs_info
->tree_root
);
249 root
->commit_root
= root
->node
;
251 ret
= btrfs_drop_snapshot(trans
, root
, snap
);
254 ret
= btrfs_del_root(trans
, root
->fs_info
->tree_root
, &snap_key
);
256 root
->fs_info
->generation
= root
->root_key
.offset
+ 1;
261 static int __setup_root(struct btrfs_super_block
*super
,
262 struct btrfs_root
*root
,
263 struct btrfs_fs_info
*fs_info
,
264 u64 objectid
, int fp
)
267 root
->commit_root
= NULL
;
268 root
->blocksize
= btrfs_super_blocksize(super
);
270 root
->fs_info
= fs_info
;
271 memset(&root
->root_key
, 0, sizeof(root
->root_key
));
272 memset(&root
->root_item
, 0, sizeof(root
->root_item
));
273 root
->root_key
.objectid
= objectid
;
277 static int find_and_setup_root(struct btrfs_super_block
*super
,
278 struct btrfs_root
*tree_root
,
279 struct btrfs_fs_info
*fs_info
,
281 struct btrfs_root
*root
, int fp
)
285 __setup_root(super
, root
, fs_info
, objectid
, fp
);
286 ret
= btrfs_find_last_root(tree_root
, objectid
,
287 &root
->root_item
, &root
->root_key
);
290 root
->node
= read_tree_block(root
,
291 btrfs_root_blocknr(&root
->root_item
));
296 struct btrfs_root
*open_ctree(char *filename
, struct btrfs_super_block
*super
)
300 fp
= open(filename
, O_CREAT
| O_RDWR
, 0600);
304 return open_ctree_fd(fp
, super
);
307 struct btrfs_root
*open_ctree_fd(int fp
, struct btrfs_super_block
*super
)
309 struct btrfs_root
*root
= malloc(sizeof(struct btrfs_root
));
310 struct btrfs_root
*extent_root
= malloc(sizeof(struct btrfs_root
));
311 struct btrfs_root
*tree_root
= malloc(sizeof(struct btrfs_root
));
312 struct btrfs_fs_info
*fs_info
= malloc(sizeof(*fs_info
));
315 INIT_RADIX_TREE(&fs_info
->cache_radix
, GFP_KERNEL
);
316 INIT_RADIX_TREE(&fs_info
->pinned_radix
, GFP_KERNEL
);
317 INIT_RADIX_TREE(&fs_info
->block_group_radix
, GFP_KERNEL
);
318 INIT_LIST_HEAD(&fs_info
->trans
);
319 INIT_LIST_HEAD(&fs_info
->cache
);
320 fs_info
->cache_size
= 0;
322 fs_info
->running_transaction
= NULL
;
323 fs_info
->fs_root
= root
;
324 fs_info
->tree_root
= tree_root
;
325 fs_info
->extent_root
= extent_root
;
326 fs_info
->last_inode_alloc
= 0;
327 fs_info
->last_inode_alloc_dirid
= 0;
328 fs_info
->disk_super
= super
;
329 memset(&fs_info
->current_insert
, 0, sizeof(fs_info
->current_insert
));
330 memset(&fs_info
->last_insert
, 0, sizeof(fs_info
->last_insert
));
332 ret
= pread(fp
, super
, sizeof(struct btrfs_super_block
),
333 BTRFS_SUPER_INFO_OFFSET
);
334 if (ret
== 0 || btrfs_super_root(super
) == 0) {
340 __setup_root(super
, tree_root
, fs_info
, BTRFS_ROOT_TREE_OBJECTID
, fp
);
341 tree_root
->node
= read_tree_block(tree_root
, btrfs_super_root(super
));
342 BUG_ON(!tree_root
->node
);
344 ret
= find_and_setup_root(super
, tree_root
, fs_info
,
345 BTRFS_EXTENT_TREE_OBJECTID
, extent_root
, fp
);
348 ret
= find_and_setup_root(super
, tree_root
, fs_info
,
349 BTRFS_FS_TREE_OBJECTID
, root
, fp
);
352 root
->commit_root
= root
->node
;
355 root
->fs_info
->generation
= root
->root_key
.offset
+ 1;
356 btrfs_read_block_groups(root
);
360 int write_ctree_super(struct btrfs_trans_handle
*trans
, struct btrfs_root
361 *root
, struct btrfs_super_block
*s
)
364 btrfs_set_super_root(s
, root
->fs_info
->tree_root
->node
->blocknr
);
365 ret
= pwrite(root
->fs_info
->fp
, s
, sizeof(*s
),
366 BTRFS_SUPER_INFO_OFFSET
);
367 if (ret
!= sizeof(*s
)) {
368 fprintf(stderr
, "failed to write new super block err %d\n", ret
);
374 static int drop_cache(struct btrfs_root
*root
)
376 while(!list_empty(&root
->fs_info
->cache
)) {
377 struct btrfs_buffer
*b
= list_entry(root
->fs_info
->cache
.next
,
380 list_del_init(&b
->cache
);
381 btrfs_block_release(root
, b
);
386 int close_ctree(struct btrfs_root
*root
, struct btrfs_super_block
*s
)
389 struct btrfs_trans_handle
*trans
;
391 trans
= root
->fs_info
->running_transaction
;
392 btrfs_commit_transaction(trans
, root
, s
);
393 ret
= commit_tree_roots(trans
, root
->fs_info
);
395 ret
= __commit_transaction(trans
, root
);
397 write_ctree_super(trans
, root
, s
);
399 BUG_ON(!list_empty(&root
->fs_info
->trans
));
401 btrfs_free_block_groups(root
->fs_info
);
402 close(root
->fs_info
->fp
);
404 btrfs_block_release(root
, root
->node
);
405 if (root
->fs_info
->extent_root
->node
)
406 btrfs_block_release(root
->fs_info
->extent_root
,
407 root
->fs_info
->extent_root
->node
);
408 if (root
->fs_info
->tree_root
->node
)
409 btrfs_block_release(root
->fs_info
->tree_root
,
410 root
->fs_info
->tree_root
->node
);
411 btrfs_block_release(root
, root
->commit_root
);
413 printf("on close %d blocks are allocated\n", allocated_blocks
);
417 void btrfs_block_release(struct btrfs_root
*root
, struct btrfs_buffer
*buf
)
422 if (buf
->count
== 0) {
423 BUG_ON(!list_empty(&buf
->cache
));
424 BUG_ON(!list_empty(&buf
->dirty
));
425 if (!radix_tree_lookup(&root
->fs_info
->cache_radix
,
428 radix_tree_delete(&root
->fs_info
->cache_radix
, buf
->blocknr
);
429 memset(buf
, 0, sizeof(*buf
));
431 BUG_ON(allocated_blocks
== 0);
433 BUG_ON(root
->fs_info
->cache_size
== 0);
434 root
->fs_info
->cache_size
--;