1 #define _XOPEN_SOURCE 600
9 #include "kerncompat.h"
10 #include "radix-tree.h"
13 #include "transaction.h"
15 static int allocated_blocks
= 0;
16 int cache_max
= 10000;
25 int btrfs_insert_dev_radix(struct btrfs_root
*root
,
31 struct dev_lookup
*lookup
;
34 lookup
= malloc(sizeof(*lookup
));
37 lookup
->block_start
= block_start
;
38 lookup
->num_blocks
= num_blocks
;
40 lookup
->device_id
= device_id
;
41 printf("inserting into dev radix %Lu %Lu\n", block_start
, num_blocks
);
43 ret
= radix_tree_insert(&root
->fs_info
->dev_radix
, block_start
+
44 num_blocks
- 1, lookup
);
48 int btrfs_map_bh_to_logical(struct btrfs_root
*root
, struct btrfs_buffer
*bh
,
51 struct dev_lookup
*lookup
[2];
55 root
= root
->fs_info
->dev_root
;
56 ret
= radix_tree_gang_lookup(&root
->fs_info
->dev_radix
,
58 (unsigned long)logical
,
60 if (ret
== 0 || lookup
[0]->block_start
> logical
||
61 lookup
[0]->block_start
+ lookup
[0]->num_blocks
<= logical
) {
65 bh
->fd
= lookup
[0]->fd
;
66 bh
->dev_blocknr
= logical
- lookup
[0]->block_start
;
72 static int check_tree_block(struct btrfs_root
*root
, struct btrfs_buffer
*buf
)
74 if (buf
->blocknr
!= btrfs_header_blocknr(&buf
->node
.header
))
76 if (memcmp(root
->fs_info
->disk_super
->fsid
, buf
->node
.header
.fsid
,
77 sizeof(buf
->node
.header
.fsid
)))
82 static int free_some_buffers(struct btrfs_root
*root
)
84 struct list_head
*node
, *next
;
85 struct btrfs_buffer
*b
;
86 if (root
->fs_info
->cache_size
< cache_max
)
88 list_for_each_safe(node
, next
, &root
->fs_info
->cache
) {
89 b
= list_entry(node
, struct btrfs_buffer
, cache
);
91 BUG_ON(!list_empty(&b
->dirty
));
92 list_del_init(&b
->cache
);
93 btrfs_block_release(root
, b
);
94 if (root
->fs_info
->cache_size
< cache_max
)
101 struct btrfs_buffer
*alloc_tree_block(struct btrfs_root
*root
, u64 blocknr
)
103 struct btrfs_buffer
*buf
;
106 buf
= malloc(sizeof(struct btrfs_buffer
) + root
->blocksize
);
110 buf
->blocknr
= blocknr
;
112 INIT_LIST_HEAD(&buf
->dirty
);
113 free_some_buffers(root
);
114 radix_tree_preload(GFP_KERNEL
);
115 ret
= radix_tree_insert(&root
->fs_info
->cache_radix
, blocknr
, buf
);
116 radix_tree_preload_end();
117 list_add_tail(&buf
->cache
, &root
->fs_info
->cache
);
118 root
->fs_info
->cache_size
++;
126 struct btrfs_buffer
*find_tree_block(struct btrfs_root
*root
, u64 blocknr
)
128 struct btrfs_buffer
*buf
;
129 buf
= radix_tree_lookup(&root
->fs_info
->cache_radix
, blocknr
);
133 buf
= alloc_tree_block(root
, blocknr
);
142 struct btrfs_buffer
*read_tree_block(struct btrfs_root
*root
, u64 blocknr
)
144 struct btrfs_buffer
*buf
;
146 buf
= radix_tree_lookup(&root
->fs_info
->cache_radix
, blocknr
);
149 if (check_tree_block(root
, buf
))
152 buf
= alloc_tree_block(root
, blocknr
);
155 btrfs_map_bh_to_logical(root
, buf
, blocknr
);
156 ret
= pread(buf
->fd
, &buf
->node
, root
->blocksize
,
157 buf
->dev_blocknr
* root
->blocksize
);
158 if (ret
!= root
->blocksize
) {
162 if (check_tree_block(root
, buf
))
168 int dirty_tree_block(struct btrfs_trans_handle
*trans
, struct btrfs_root
*root
,
169 struct btrfs_buffer
*buf
)
171 if (!list_empty(&buf
->dirty
))
173 list_add_tail(&buf
->dirty
, &root
->fs_info
->trans
);
175 if (check_tree_block(root
, buf
))
180 int clean_tree_block(struct btrfs_trans_handle
*trans
, struct btrfs_root
*root
,
181 struct btrfs_buffer
*buf
)
183 if (!list_empty(&buf
->dirty
)) {
184 list_del_init(&buf
->dirty
);
185 btrfs_block_release(root
, buf
);
190 int write_tree_block(struct btrfs_trans_handle
*trans
, struct btrfs_root
*root
,
191 struct btrfs_buffer
*buf
)
195 if (buf
->blocknr
!= btrfs_header_blocknr(&buf
->node
.header
))
197 btrfs_map_bh_to_logical(root
, buf
, buf
->blocknr
);
198 if (check_tree_block(root
, buf
))
200 ret
= pwrite(buf
->fd
, &buf
->node
, root
->blocksize
,
201 buf
->dev_blocknr
* root
->blocksize
);
202 if (ret
!= root
->blocksize
)
207 static int __commit_transaction(struct btrfs_trans_handle
*trans
, struct
210 struct btrfs_buffer
*b
;
213 while(!list_empty(&root
->fs_info
->trans
)) {
214 b
= list_entry(root
->fs_info
->trans
.next
, struct btrfs_buffer
,
216 list_del_init(&b
->dirty
);
217 wret
= write_tree_block(trans
, root
, b
);
220 btrfs_block_release(root
, b
);
225 static int commit_tree_roots(struct btrfs_trans_handle
*trans
,
226 struct btrfs_fs_info
*fs_info
)
229 u64 old_extent_block
;
230 struct btrfs_root
*tree_root
= fs_info
->tree_root
;
231 struct btrfs_root
*extent_root
= fs_info
->extent_root
;
233 if (btrfs_super_device_root(fs_info
->disk_super
) !=
234 fs_info
->dev_root
->node
->blocknr
) {
235 btrfs_set_super_device_root(fs_info
->disk_super
,
236 fs_info
->dev_root
->node
->blocknr
);
238 btrfs_write_dirty_block_groups(trans
, fs_info
->extent_root
);
240 old_extent_block
= btrfs_root_blocknr(&extent_root
->root_item
);
241 if (old_extent_block
== extent_root
->node
->blocknr
)
243 btrfs_set_root_blocknr(&extent_root
->root_item
,
244 extent_root
->node
->blocknr
);
245 ret
= btrfs_update_root(trans
, tree_root
,
246 &extent_root
->root_key
,
247 &extent_root
->root_item
);
249 btrfs_write_dirty_block_groups(trans
, fs_info
->extent_root
);
254 int btrfs_commit_transaction(struct btrfs_trans_handle
*trans
, struct
255 btrfs_root
*root
, struct btrfs_super_block
*s
)
258 struct btrfs_buffer
*snap
= root
->commit_root
;
259 struct btrfs_key snap_key
;
261 if (root
->commit_root
== root
->node
)
264 memcpy(&snap_key
, &root
->root_key
, sizeof(snap_key
));
265 root
->root_key
.offset
++;
267 btrfs_set_root_blocknr(&root
->root_item
, root
->node
->blocknr
);
268 ret
= btrfs_insert_root(trans
, root
->fs_info
->tree_root
,
269 &root
->root_key
, &root
->root_item
);
272 ret
= commit_tree_roots(trans
, root
->fs_info
);
275 ret
= __commit_transaction(trans
, root
);
278 write_ctree_super(trans
, root
, s
);
279 btrfs_finish_extent_commit(trans
, root
->fs_info
->extent_root
);
280 btrfs_finish_extent_commit(trans
, root
->fs_info
->tree_root
);
282 root
->commit_root
= root
->node
;
284 ret
= btrfs_drop_snapshot(trans
, root
, snap
);
287 ret
= btrfs_del_root(trans
, root
->fs_info
->tree_root
, &snap_key
);
289 root
->fs_info
->generation
= root
->root_key
.offset
+ 1;
294 static int __setup_root(struct btrfs_super_block
*super
,
295 struct btrfs_root
*root
,
296 struct btrfs_fs_info
*fs_info
,
297 u64 objectid
, int fp
)
300 root
->commit_root
= NULL
;
301 root
->blocksize
= btrfs_super_blocksize(super
);
303 root
->fs_info
= fs_info
;
304 memset(&root
->root_key
, 0, sizeof(root
->root_key
));
305 memset(&root
->root_item
, 0, sizeof(root
->root_item
));
306 root
->root_key
.objectid
= objectid
;
310 static int find_and_setup_root(struct btrfs_super_block
*super
,
311 struct btrfs_root
*tree_root
,
312 struct btrfs_fs_info
*fs_info
,
314 struct btrfs_root
*root
, int fp
)
318 __setup_root(super
, root
, fs_info
, objectid
, fp
);
319 ret
= btrfs_find_last_root(tree_root
, objectid
,
320 &root
->root_item
, &root
->root_key
);
323 root
->node
= read_tree_block(root
,
324 btrfs_root_blocknr(&root
->root_item
));
329 int btrfs_open_disk(struct btrfs_root
*root
, u64 device_id
,
330 u64 block_start
, u64 num_blocks
,
331 char *filename
, int name_len
)
337 null_filename
= malloc(name_len
+ 1);
340 memcpy(null_filename
, filename
, name_len
);
341 null_filename
[name_len
] = '\0';
343 fd
= open(null_filename
, O_RDWR
);
349 posix_fadvise(fd
, 0, 0, POSIX_FADV_RANDOM
);
350 posix_fadvise(fd
, 0, 0, POSIX_FADV_NOREUSE
);
351 ret
= btrfs_insert_dev_radix(root
, fd
, device_id
,
352 block_start
, num_blocks
);
360 static int read_device_info(struct btrfs_root
*root
)
362 struct btrfs_path path
;
364 struct btrfs_key key
;
365 struct btrfs_leaf
*leaf
;
366 struct btrfs_device_item
*dev_item
;
370 root
= root
->fs_info
->dev_root
;
372 btrfs_init_path(&path
);
376 btrfs_set_key_type(&key
, BTRFS_DEV_ITEM_KEY
);
378 ret
= btrfs_search_slot(NULL
, root
, &key
, &path
, 0, 0);
379 leaf
= &path
.nodes
[0]->leaf
;
380 nritems
= btrfs_header_nritems(&leaf
->header
);
382 slot
= path
.slots
[0];
383 if (slot
>= nritems
) {
384 ret
= btrfs_next_leaf(root
, &path
);
387 leaf
= &path
.nodes
[0]->leaf
;
388 nritems
= btrfs_header_nritems(&leaf
->header
);
389 slot
= path
.slots
[0];
391 btrfs_disk_key_to_cpu(&key
, &leaf
->items
[slot
].key
);
392 if (btrfs_key_type(&key
) != BTRFS_DEV_ITEM_KEY
) {
396 dev_item
= btrfs_item_ptr(leaf
, slot
, struct btrfs_device_item
);
397 if (btrfs_device_id(dev_item
) !=
398 btrfs_super_device_id(root
->fs_info
->disk_super
)) {
399 printf("found key %Lu %Lu\n", key
.objectid
, key
.offset
);
400 ret
= btrfs_open_disk(root
, btrfs_device_id(dev_item
),
401 key
.objectid
, key
.offset
,
402 (char *)(dev_item
+ 1),
403 btrfs_device_pathlen(dev_item
));
408 btrfs_release_path(root
, &path
);
412 struct btrfs_root
*open_ctree(char *filename
, struct btrfs_super_block
*super
)
416 fp
= open(filename
, O_CREAT
| O_RDWR
, 0600);
420 return open_ctree_fd(fp
, super
);
423 struct btrfs_root
*open_ctree_fd(int fp
, struct btrfs_super_block
*super
)
425 struct btrfs_root
*root
= malloc(sizeof(struct btrfs_root
));
426 struct btrfs_root
*extent_root
= malloc(sizeof(struct btrfs_root
));
427 struct btrfs_root
*tree_root
= malloc(sizeof(struct btrfs_root
));
428 struct btrfs_root
*dev_root
= malloc(sizeof(struct btrfs_root
));
429 struct btrfs_fs_info
*fs_info
= malloc(sizeof(*fs_info
));
430 struct dev_lookup
*dev_lookup
;
433 INIT_RADIX_TREE(&fs_info
->cache_radix
, GFP_KERNEL
);
434 INIT_RADIX_TREE(&fs_info
->pinned_radix
, GFP_KERNEL
);
435 INIT_RADIX_TREE(&fs_info
->dev_radix
, GFP_KERNEL
);
436 INIT_RADIX_TREE(&fs_info
->block_group_radix
, GFP_KERNEL
);
437 INIT_LIST_HEAD(&fs_info
->trans
);
438 INIT_LIST_HEAD(&fs_info
->cache
);
439 fs_info
->cache_size
= 0;
441 fs_info
->running_transaction
= NULL
;
442 fs_info
->fs_root
= root
;
443 fs_info
->tree_root
= tree_root
;
444 fs_info
->extent_root
= extent_root
;
445 fs_info
->dev_root
= dev_root
;
446 fs_info
->last_inode_alloc
= 0;
447 fs_info
->last_inode_alloc_dirid
= 0;
448 fs_info
->disk_super
= super
;
449 memset(&fs_info
->current_insert
, 0, sizeof(fs_info
->current_insert
));
450 memset(&fs_info
->last_insert
, 0, sizeof(fs_info
->last_insert
));
452 ret
= pread(fp
, super
, sizeof(struct btrfs_super_block
),
453 BTRFS_SUPER_INFO_OFFSET
);
454 if (ret
== 0 || btrfs_super_root(super
) == 0) {
459 __setup_root(super
, dev_root
, fs_info
, BTRFS_DEV_TREE_OBJECTID
, fp
);
461 dev_lookup
= malloc(sizeof(*dev_lookup
));
463 dev_lookup
->device_id
= btrfs_super_device_id(super
);
464 dev_lookup
->block_start
= btrfs_super_device_block_start(super
);
465 dev_lookup
->num_blocks
= btrfs_super_device_num_blocks(super
);
466 ret
= radix_tree_insert(&fs_info
->dev_radix
,
467 dev_lookup
->block_start
+
468 dev_lookup
->num_blocks
- 1, dev_lookup
);
471 dev_root
->node
= read_tree_block(dev_root
,
472 btrfs_super_device_root(super
));
474 ret
= read_device_info(dev_root
);
477 __setup_root(super
, tree_root
, fs_info
, BTRFS_ROOT_TREE_OBJECTID
, fp
);
478 tree_root
->node
= read_tree_block(tree_root
, btrfs_super_root(super
));
479 BUG_ON(!tree_root
->node
);
481 ret
= find_and_setup_root(super
, tree_root
, fs_info
,
482 BTRFS_EXTENT_TREE_OBJECTID
, extent_root
, fp
);
485 ret
= find_and_setup_root(super
, tree_root
, fs_info
,
486 BTRFS_FS_TREE_OBJECTID
, root
, fp
);
489 root
->commit_root
= root
->node
;
492 root
->fs_info
->generation
= root
->root_key
.offset
+ 1;
493 btrfs_read_block_groups(root
);
497 int write_ctree_super(struct btrfs_trans_handle
*trans
, struct btrfs_root
498 *root
, struct btrfs_super_block
*s
)
501 btrfs_set_super_root(s
, root
->fs_info
->tree_root
->node
->blocknr
);
502 ret
= pwrite(root
->fs_info
->fp
, s
, sizeof(*s
),
503 BTRFS_SUPER_INFO_OFFSET
);
504 if (ret
!= sizeof(*s
)) {
505 fprintf(stderr
, "failed to write new super block err %d\n", ret
);
511 static int drop_cache(struct btrfs_root
*root
)
513 while(!list_empty(&root
->fs_info
->cache
)) {
514 struct btrfs_buffer
*b
= list_entry(root
->fs_info
->cache
.next
,
517 list_del_init(&b
->cache
);
518 btrfs_block_release(root
, b
);
523 static int free_dev_radix(struct btrfs_fs_info
*fs_info
)
525 struct dev_lookup
*lookup
[8];
529 ret
= radix_tree_gang_lookup(&fs_info
->dev_radix
,
534 for (i
= 0; i
< ret
; i
++) {
535 if (lookup
[i
]->device_id
!=
536 btrfs_super_device_id(fs_info
->disk_super
))
537 close(lookup
[i
]->fd
);
538 radix_tree_delete(&fs_info
->dev_radix
,
539 lookup
[i
]->block_start
+
540 lookup
[i
]->num_blocks
- 1);
547 int close_ctree(struct btrfs_root
*root
, struct btrfs_super_block
*s
)
550 struct btrfs_trans_handle
*trans
;
552 trans
= root
->fs_info
->running_transaction
;
553 btrfs_commit_transaction(trans
, root
, s
);
554 ret
= commit_tree_roots(trans
, root
->fs_info
);
556 ret
= __commit_transaction(trans
, root
);
558 write_ctree_super(trans
, root
, s
);
560 BUG_ON(!list_empty(&root
->fs_info
->trans
));
562 free_dev_radix(root
->fs_info
);
563 btrfs_free_block_groups(root
->fs_info
);
564 close(root
->fs_info
->fp
);
566 btrfs_block_release(root
, root
->node
);
567 if (root
->fs_info
->extent_root
->node
)
568 btrfs_block_release(root
->fs_info
->extent_root
,
569 root
->fs_info
->extent_root
->node
);
570 if (root
->fs_info
->tree_root
->node
)
571 btrfs_block_release(root
->fs_info
->tree_root
,
572 root
->fs_info
->tree_root
->node
);
573 if (root
->fs_info
->dev_root
->node
)
574 btrfs_block_release(root
->fs_info
->dev_root
,
575 root
->fs_info
->dev_root
->node
);
576 btrfs_block_release(root
, root
->commit_root
);
578 printf("on close %d blocks are allocated\n", allocated_blocks
);
582 void btrfs_block_release(struct btrfs_root
*root
, struct btrfs_buffer
*buf
)
587 if (buf
->count
== 0) {
588 BUG_ON(!list_empty(&buf
->cache
));
589 BUG_ON(!list_empty(&buf
->dirty
));
590 if (!radix_tree_lookup(&root
->fs_info
->cache_radix
,
593 radix_tree_delete(&root
->fs_info
->cache_radix
, buf
->blocknr
);
594 memset(buf
, 0, sizeof(*buf
));
596 BUG_ON(allocated_blocks
== 0);
598 BUG_ON(root
->fs_info
->cache_size
== 0);
599 root
->fs_info
->cache_size
--;