1 #define _XOPEN_SOURCE 500
8 #include "kerncompat.h"
9 #include "radix-tree.h"
12 #include "transaction.h"
14 static int allocated_blocks
= 0;
15 int cache_max
= 10000;
17 static int check_tree_block(struct btrfs_root
*root
, struct btrfs_buffer
*buf
)
19 if (buf
->blocknr
!= btrfs_header_blocknr(&buf
->node
.header
))
21 if (root
->node
&& btrfs_header_parentid(&buf
->node
.header
) !=
22 btrfs_header_parentid(&root
->node
->node
.header
))
27 static int free_some_buffers(struct btrfs_root
*root
)
29 struct list_head
*node
, *next
;
30 struct btrfs_buffer
*b
;
31 if (root
->fs_info
->cache_size
< cache_max
)
33 list_for_each_safe(node
, next
, &root
->fs_info
->cache
) {
34 b
= list_entry(node
, struct btrfs_buffer
, cache
);
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
)
46 struct btrfs_buffer
*alloc_tree_block(struct btrfs_root
*root
, u64 blocknr
)
48 struct btrfs_buffer
*buf
;
51 buf
= malloc(sizeof(struct btrfs_buffer
) + root
->blocksize
);
55 buf
->blocknr
= blocknr
;
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
++;
71 struct btrfs_buffer
*find_tree_block(struct btrfs_root
*root
, u64 blocknr
)
73 struct btrfs_buffer
*buf
;
74 buf
= radix_tree_lookup(&root
->fs_info
->cache_radix
, blocknr
);
78 buf
= alloc_tree_block(root
, blocknr
);
87 struct btrfs_buffer
*read_tree_block(struct btrfs_root
*root
, u64 blocknr
)
89 loff_t offset
= blocknr
* root
->blocksize
;
90 struct btrfs_buffer
*buf
;
93 buf
= radix_tree_lookup(&root
->fs_info
->cache_radix
, blocknr
);
97 buf
= alloc_tree_block(root
, blocknr
);
100 ret
= pread(root
->fs_info
->fp
, &buf
->node
, root
->blocksize
,
102 if (ret
!= root
->blocksize
) {
107 if (check_tree_block(root
, buf
))
112 int dirty_tree_block(struct btrfs_trans_handle
*trans
, struct btrfs_root
*root
,
113 struct btrfs_buffer
*buf
)
115 if (!list_empty(&buf
->dirty
))
117 list_add_tail(&buf
->dirty
, &root
->fs_info
->trans
);
122 int clean_tree_block(struct btrfs_trans_handle
*trans
, struct btrfs_root
*root
,
123 struct btrfs_buffer
*buf
)
125 if (!list_empty(&buf
->dirty
)) {
126 list_del_init(&buf
->dirty
);
127 btrfs_block_release(root
, buf
);
132 int write_tree_block(struct btrfs_trans_handle
*trans
, struct btrfs_root
*root
,
133 struct btrfs_buffer
*buf
)
135 u64 blocknr
= buf
->blocknr
;
136 loff_t offset
= blocknr
* root
->blocksize
;
139 if (buf
->blocknr
!= btrfs_header_blocknr(&buf
->node
.header
))
141 ret
= pwrite(root
->fs_info
->fp
, &buf
->node
, root
->blocksize
, offset
);
142 if (ret
!= root
->blocksize
)
147 static int __commit_transaction(struct btrfs_trans_handle
*trans
, struct
150 struct btrfs_buffer
*b
;
153 while(!list_empty(&root
->fs_info
->trans
)) {
154 b
= list_entry(root
->fs_info
->trans
.next
, struct btrfs_buffer
,
156 list_del_init(&b
->dirty
);
157 wret
= write_tree_block(trans
, root
, b
);
160 btrfs_block_release(root
, b
);
165 static int commit_tree_roots(struct btrfs_trans_handle
*trans
,
166 struct btrfs_fs_info
*fs_info
)
169 u64 old_extent_block
;
170 struct btrfs_root
*tree_root
= fs_info
->tree_root
;
171 struct btrfs_root
*extent_root
= fs_info
->extent_root
;
172 struct btrfs_root
*inode_root
= fs_info
->inode_root
;
174 btrfs_set_root_blocknr(&inode_root
->root_item
,
175 inode_root
->node
->blocknr
);
176 ret
= btrfs_update_root(trans
, tree_root
,
177 &inode_root
->root_key
,
178 &inode_root
->root_item
);
181 old_extent_block
= btrfs_root_blocknr(&extent_root
->root_item
);
182 if (old_extent_block
== extent_root
->node
->blocknr
)
184 btrfs_set_root_blocknr(&extent_root
->root_item
,
185 extent_root
->node
->blocknr
);
186 ret
= btrfs_update_root(trans
, tree_root
,
187 &extent_root
->root_key
,
188 &extent_root
->root_item
);
194 int btrfs_commit_transaction(struct btrfs_trans_handle
*trans
, struct
195 btrfs_root
*root
, struct btrfs_super_block
*s
)
198 struct btrfs_buffer
*snap
= root
->commit_root
;
199 struct btrfs_key snap_key
;
201 if (root
->commit_root
== root
->node
)
204 memcpy(&snap_key
, &root
->root_key
, sizeof(snap_key
));
205 root
->root_key
.offset
++;
207 btrfs_set_root_blocknr(&root
->root_item
, root
->node
->blocknr
);
208 ret
= btrfs_insert_root(trans
, root
->fs_info
->tree_root
,
209 &root
->root_key
, &root
->root_item
);
212 ret
= commit_tree_roots(trans
, root
->fs_info
);
215 ret
= __commit_transaction(trans
, root
);
218 write_ctree_super(trans
, root
, s
);
219 btrfs_finish_extent_commit(trans
, root
->fs_info
->extent_root
);
220 btrfs_finish_extent_commit(trans
, root
->fs_info
->tree_root
);
222 root
->commit_root
= root
->node
;
224 ret
= btrfs_drop_snapshot(trans
, root
, snap
);
227 ret
= btrfs_del_root(trans
, root
->fs_info
->tree_root
, &snap_key
);
233 static int __setup_root(struct btrfs_super_block
*super
,
234 struct btrfs_root
*root
,
235 struct btrfs_fs_info
*fs_info
,
236 u64 objectid
, int fp
)
239 root
->commit_root
= NULL
;
240 root
->blocksize
= btrfs_super_blocksize(super
);
242 root
->fs_info
= fs_info
;
243 memset(&root
->root_key
, 0, sizeof(root
->root_key
));
244 memset(&root
->root_item
, 0, sizeof(root
->root_item
));
248 static int find_and_setup_root(struct btrfs_super_block
*super
,
249 struct btrfs_root
*tree_root
,
250 struct btrfs_fs_info
*fs_info
,
252 struct btrfs_root
*root
, int fp
)
256 __setup_root(super
, root
, fs_info
, objectid
, fp
);
257 ret
= btrfs_find_last_root(tree_root
, objectid
,
258 &root
->root_item
, &root
->root_key
);
261 root
->node
= read_tree_block(root
,
262 btrfs_root_blocknr(&root
->root_item
));
267 struct btrfs_root
*open_ctree(char *filename
, struct btrfs_super_block
*super
)
269 struct btrfs_root
*root
= malloc(sizeof(struct btrfs_root
));
270 struct btrfs_root
*extent_root
= malloc(sizeof(struct btrfs_root
));
271 struct btrfs_root
*tree_root
= malloc(sizeof(struct btrfs_root
));
272 struct btrfs_root
*inode_root
= malloc(sizeof(struct btrfs_root
));
273 struct btrfs_fs_info
*fs_info
= malloc(sizeof(*fs_info
));
277 fp
= open(filename
, O_CREAT
| O_RDWR
, 0600);
282 INIT_RADIX_TREE(&fs_info
->cache_radix
, GFP_KERNEL
);
283 INIT_RADIX_TREE(&fs_info
->pinned_radix
, GFP_KERNEL
);
284 INIT_LIST_HEAD(&fs_info
->trans
);
285 INIT_LIST_HEAD(&fs_info
->cache
);
286 fs_info
->cache_size
= 0;
288 fs_info
->running_transaction
= NULL
;
289 fs_info
->fs_root
= root
;
290 fs_info
->tree_root
= tree_root
;
291 fs_info
->extent_root
= extent_root
;
292 fs_info
->inode_root
= inode_root
;
293 fs_info
->last_inode_alloc
= 0;
294 fs_info
->last_inode_alloc_dirid
= 0;
295 memset(&fs_info
->current_insert
, 0, sizeof(fs_info
->current_insert
));
296 memset(&fs_info
->last_insert
, 0, sizeof(fs_info
->last_insert
));
298 ret
= pread(fp
, super
, sizeof(struct btrfs_super_block
),
299 BTRFS_SUPER_INFO_OFFSET
);
300 if (ret
== 0 || btrfs_super_root(super
) == 0) {
301 printf("making new FS!\n");
302 ret
= mkfs(fp
, 0, 1024);
305 ret
= pread(fp
, super
, sizeof(struct btrfs_super_block
),
306 BTRFS_SUPER_INFO_OFFSET
);
307 if (ret
!= sizeof(struct btrfs_super_block
))
312 __setup_root(super
, tree_root
, fs_info
, BTRFS_ROOT_TREE_OBJECTID
, fp
);
313 tree_root
->node
= read_tree_block(tree_root
, btrfs_super_root(super
));
314 BUG_ON(!tree_root
->node
);
316 ret
= find_and_setup_root(super
, tree_root
, fs_info
,
317 BTRFS_EXTENT_TREE_OBJECTID
, extent_root
, fp
);
320 ret
= find_and_setup_root(super
, tree_root
, fs_info
,
321 BTRFS_INODE_MAP_OBJECTID
, inode_root
, fp
);
324 ret
= find_and_setup_root(super
, tree_root
, fs_info
,
325 BTRFS_FS_TREE_OBJECTID
, root
, fp
);
328 root
->commit_root
= root
->node
;
334 int write_ctree_super(struct btrfs_trans_handle
*trans
, struct btrfs_root
335 *root
, struct btrfs_super_block
*s
)
338 btrfs_set_super_root(s
, root
->fs_info
->tree_root
->node
->blocknr
);
339 ret
= pwrite(root
->fs_info
->fp
, s
, sizeof(*s
),
340 BTRFS_SUPER_INFO_OFFSET
);
341 if (ret
!= sizeof(*s
)) {
342 fprintf(stderr
, "failed to write new super block err %d\n", ret
);
348 static int drop_cache(struct btrfs_root
*root
)
350 while(!list_empty(&root
->fs_info
->cache
)) {
351 struct btrfs_buffer
*b
= list_entry(root
->fs_info
->cache
.next
,
354 list_del_init(&b
->cache
);
355 btrfs_block_release(root
, b
);
359 int close_ctree(struct btrfs_root
*root
, struct btrfs_super_block
*s
)
362 struct btrfs_trans_handle
*trans
;
364 trans
= root
->fs_info
->running_transaction
;
365 btrfs_commit_transaction(trans
, root
, s
);
366 ret
= commit_tree_roots(trans
, root
->fs_info
);
368 ret
= __commit_transaction(trans
, root
);
370 write_ctree_super(trans
, root
, s
);
372 BUG_ON(!list_empty(&root
->fs_info
->trans
));
374 close(root
->fs_info
->fp
);
376 btrfs_block_release(root
, root
->node
);
377 if (root
->fs_info
->extent_root
->node
)
378 btrfs_block_release(root
->fs_info
->extent_root
,
379 root
->fs_info
->extent_root
->node
);
380 if (root
->fs_info
->inode_root
->node
)
381 btrfs_block_release(root
->fs_info
->inode_root
,
382 root
->fs_info
->inode_root
->node
);
383 if (root
->fs_info
->tree_root
->node
)
384 btrfs_block_release(root
->fs_info
->tree_root
,
385 root
->fs_info
->tree_root
->node
);
386 btrfs_block_release(root
, root
->commit_root
);
388 printf("on close %d blocks are allocated\n", allocated_blocks
);
392 void btrfs_block_release(struct btrfs_root
*root
, struct btrfs_buffer
*buf
)
397 if (buf
->count
== 0) {
398 BUG_ON(!list_empty(&buf
->cache
));
399 BUG_ON(!list_empty(&buf
->dirty
));
400 if (!radix_tree_lookup(&root
->fs_info
->cache_radix
,
403 radix_tree_delete(&root
->fs_info
->cache_radix
, buf
->blocknr
);
404 memset(buf
, 0, sizeof(*buf
));
406 BUG_ON(allocated_blocks
== 0);
408 BUG_ON(root
->fs_info
->cache_size
== 0);
409 root
->fs_info
->cache_size
--;