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;
18 int btrfs_map_bh_to_logical(struct btrfs_root
*root
, struct btrfs_buffer
*bh
,
21 bh
->fd
= root
->fs_info
->fp
;
22 bh
->dev_blocknr
= logical
;
26 static int check_tree_block(struct btrfs_root
*root
, struct btrfs_buffer
*buf
)
28 if (buf
->blocknr
!= btrfs_header_blocknr(&buf
->node
.header
))
30 if (memcmp(root
->fs_info
->disk_super
->fsid
, buf
->node
.header
.fsid
,
31 sizeof(buf
->node
.header
.fsid
)))
36 static int free_some_buffers(struct btrfs_root
*root
)
38 struct list_head
*node
, *next
;
39 struct btrfs_buffer
*b
;
40 if (root
->fs_info
->cache_size
< cache_max
)
42 list_for_each_safe(node
, next
, &root
->fs_info
->cache
) {
43 b
= list_entry(node
, struct btrfs_buffer
, cache
);
45 BUG_ON(!list_empty(&b
->dirty
));
46 list_del_init(&b
->cache
);
47 btrfs_block_release(root
, b
);
48 if (root
->fs_info
->cache_size
< cache_max
)
55 struct btrfs_buffer
*alloc_tree_block(struct btrfs_root
*root
, u64 blocknr
)
57 struct btrfs_buffer
*buf
;
60 buf
= malloc(sizeof(struct btrfs_buffer
) + root
->blocksize
);
64 buf
->blocknr
= blocknr
;
66 INIT_LIST_HEAD(&buf
->dirty
);
67 free_some_buffers(root
);
68 radix_tree_preload(GFP_KERNEL
);
69 ret
= radix_tree_insert(&root
->fs_info
->cache_radix
, blocknr
, buf
);
70 radix_tree_preload_end();
71 list_add_tail(&buf
->cache
, &root
->fs_info
->cache
);
72 root
->fs_info
->cache_size
++;
80 struct btrfs_buffer
*find_tree_block(struct btrfs_root
*root
, u64 blocknr
)
82 struct btrfs_buffer
*buf
;
83 buf
= radix_tree_lookup(&root
->fs_info
->cache_radix
, blocknr
);
87 buf
= alloc_tree_block(root
, blocknr
);
96 struct btrfs_buffer
*read_tree_block(struct btrfs_root
*root
, u64 blocknr
)
98 struct btrfs_buffer
*buf
;
100 buf
= radix_tree_lookup(&root
->fs_info
->cache_radix
, blocknr
);
103 if (check_tree_block(root
, buf
))
106 buf
= alloc_tree_block(root
, blocknr
);
109 btrfs_map_bh_to_logical(root
, buf
, blocknr
);
110 ret
= pread(buf
->fd
, &buf
->node
, root
->blocksize
,
111 buf
->dev_blocknr
* root
->blocksize
);
112 if (ret
!= root
->blocksize
) {
116 if (check_tree_block(root
, buf
))
122 int dirty_tree_block(struct btrfs_trans_handle
*trans
, struct btrfs_root
*root
,
123 struct btrfs_buffer
*buf
)
125 if (!list_empty(&buf
->dirty
))
127 list_add_tail(&buf
->dirty
, &root
->fs_info
->trans
);
129 if (check_tree_block(root
, buf
))
134 int clean_tree_block(struct btrfs_trans_handle
*trans
, struct btrfs_root
*root
,
135 struct btrfs_buffer
*buf
)
137 if (!list_empty(&buf
->dirty
)) {
138 list_del_init(&buf
->dirty
);
139 btrfs_block_release(root
, buf
);
144 int write_tree_block(struct btrfs_trans_handle
*trans
, struct btrfs_root
*root
,
145 struct btrfs_buffer
*buf
)
149 if (buf
->blocknr
!= btrfs_header_blocknr(&buf
->node
.header
))
151 btrfs_map_bh_to_logical(root
, buf
, buf
->blocknr
);
152 if (check_tree_block(root
, buf
))
154 ret
= pwrite(buf
->fd
, &buf
->node
, root
->blocksize
,
155 buf
->dev_blocknr
* root
->blocksize
);
156 if (ret
!= root
->blocksize
)
161 static int __commit_transaction(struct btrfs_trans_handle
*trans
, struct
164 struct btrfs_buffer
*b
;
167 while(!list_empty(&root
->fs_info
->trans
)) {
168 b
= list_entry(root
->fs_info
->trans
.next
, struct btrfs_buffer
,
170 list_del_init(&b
->dirty
);
171 wret
= write_tree_block(trans
, root
, b
);
174 btrfs_block_release(root
, b
);
179 static int commit_tree_roots(struct btrfs_trans_handle
*trans
,
180 struct btrfs_fs_info
*fs_info
)
183 u64 old_extent_block
;
184 struct btrfs_root
*tree_root
= fs_info
->tree_root
;
185 struct btrfs_root
*extent_root
= fs_info
->extent_root
;
187 btrfs_write_dirty_block_groups(trans
, fs_info
->extent_root
);
189 old_extent_block
= btrfs_root_blocknr(&extent_root
->root_item
);
190 if (old_extent_block
== extent_root
->node
->blocknr
)
192 btrfs_set_root_blocknr(&extent_root
->root_item
,
193 extent_root
->node
->blocknr
);
194 ret
= btrfs_update_root(trans
, tree_root
,
195 &extent_root
->root_key
,
196 &extent_root
->root_item
);
198 btrfs_write_dirty_block_groups(trans
, fs_info
->extent_root
);
203 int btrfs_commit_transaction(struct btrfs_trans_handle
*trans
, struct
204 btrfs_root
*root
, struct btrfs_super_block
*s
)
207 struct btrfs_buffer
*snap
= root
->commit_root
;
208 struct btrfs_key snap_key
;
210 if (root
->commit_root
== root
->node
)
213 memcpy(&snap_key
, &root
->root_key
, sizeof(snap_key
));
214 root
->root_key
.offset
++;
216 btrfs_set_root_blocknr(&root
->root_item
, root
->node
->blocknr
);
217 ret
= btrfs_insert_root(trans
, root
->fs_info
->tree_root
,
218 &root
->root_key
, &root
->root_item
);
221 ret
= commit_tree_roots(trans
, root
->fs_info
);
224 ret
= __commit_transaction(trans
, root
);
227 write_ctree_super(trans
, root
, s
);
228 btrfs_finish_extent_commit(trans
, root
->fs_info
->extent_root
);
229 btrfs_finish_extent_commit(trans
, root
->fs_info
->tree_root
);
231 root
->commit_root
= root
->node
;
233 ret
= btrfs_drop_snapshot(trans
, root
, snap
);
236 ret
= btrfs_del_root(trans
, root
->fs_info
->tree_root
, &snap_key
);
238 root
->fs_info
->generation
= root
->root_key
.offset
+ 1;
243 static int __setup_root(struct btrfs_super_block
*super
,
244 struct btrfs_root
*root
,
245 struct btrfs_fs_info
*fs_info
,
246 u64 objectid
, int fp
)
249 root
->commit_root
= NULL
;
250 root
->blocksize
= btrfs_super_blocksize(super
);
252 root
->fs_info
= fs_info
;
253 memset(&root
->root_key
, 0, sizeof(root
->root_key
));
254 memset(&root
->root_item
, 0, sizeof(root
->root_item
));
255 root
->root_key
.objectid
= objectid
;
259 static int find_and_setup_root(struct btrfs_super_block
*super
,
260 struct btrfs_root
*tree_root
,
261 struct btrfs_fs_info
*fs_info
,
263 struct btrfs_root
*root
, int fp
)
267 __setup_root(super
, root
, fs_info
, objectid
, fp
);
268 ret
= btrfs_find_last_root(tree_root
, objectid
,
269 &root
->root_item
, &root
->root_key
);
272 root
->node
= read_tree_block(root
,
273 btrfs_root_blocknr(&root
->root_item
));
278 struct btrfs_root
*open_ctree(char *filename
, struct btrfs_super_block
*super
)
282 fp
= open(filename
, O_CREAT
| O_RDWR
, 0600);
286 return open_ctree_fd(fp
, super
);
289 struct btrfs_root
*open_ctree_fd(int fp
, struct btrfs_super_block
*super
)
291 struct btrfs_root
*root
= malloc(sizeof(struct btrfs_root
));
292 struct btrfs_root
*extent_root
= malloc(sizeof(struct btrfs_root
));
293 struct btrfs_root
*tree_root
= malloc(sizeof(struct btrfs_root
));
294 struct btrfs_fs_info
*fs_info
= malloc(sizeof(*fs_info
));
297 INIT_RADIX_TREE(&fs_info
->cache_radix
, GFP_KERNEL
);
298 INIT_RADIX_TREE(&fs_info
->pinned_radix
, GFP_KERNEL
);
299 INIT_RADIX_TREE(&fs_info
->block_group_radix
, GFP_KERNEL
);
300 INIT_LIST_HEAD(&fs_info
->trans
);
301 INIT_LIST_HEAD(&fs_info
->cache
);
302 fs_info
->cache_size
= 0;
304 fs_info
->running_transaction
= NULL
;
305 fs_info
->fs_root
= root
;
306 fs_info
->tree_root
= tree_root
;
307 fs_info
->extent_root
= extent_root
;
308 fs_info
->last_inode_alloc
= 0;
309 fs_info
->last_inode_alloc_dirid
= 0;
310 fs_info
->disk_super
= super
;
311 memset(&fs_info
->current_insert
, 0, sizeof(fs_info
->current_insert
));
312 memset(&fs_info
->last_insert
, 0, sizeof(fs_info
->last_insert
));
314 ret
= pread(fp
, super
, sizeof(struct btrfs_super_block
),
315 BTRFS_SUPER_INFO_OFFSET
);
316 if (ret
== 0 || btrfs_super_root(super
) == 0) {
322 __setup_root(super
, tree_root
, fs_info
, BTRFS_ROOT_TREE_OBJECTID
, fp
);
323 tree_root
->node
= read_tree_block(tree_root
, btrfs_super_root(super
));
324 BUG_ON(!tree_root
->node
);
326 ret
= find_and_setup_root(super
, tree_root
, fs_info
,
327 BTRFS_EXTENT_TREE_OBJECTID
, extent_root
, fp
);
330 ret
= find_and_setup_root(super
, tree_root
, fs_info
,
331 BTRFS_FS_TREE_OBJECTID
, root
, fp
);
334 root
->commit_root
= root
->node
;
337 root
->fs_info
->generation
= root
->root_key
.offset
+ 1;
338 btrfs_read_block_groups(root
);
342 int write_ctree_super(struct btrfs_trans_handle
*trans
, struct btrfs_root
343 *root
, struct btrfs_super_block
*s
)
346 btrfs_set_super_root(s
, root
->fs_info
->tree_root
->node
->blocknr
);
347 ret
= pwrite(root
->fs_info
->fp
, s
, sizeof(*s
),
348 BTRFS_SUPER_INFO_OFFSET
);
349 if (ret
!= sizeof(*s
)) {
350 fprintf(stderr
, "failed to write new super block err %d\n", ret
);
356 static int drop_cache(struct btrfs_root
*root
)
358 while(!list_empty(&root
->fs_info
->cache
)) {
359 struct btrfs_buffer
*b
= list_entry(root
->fs_info
->cache
.next
,
362 list_del_init(&b
->cache
);
363 btrfs_block_release(root
, b
);
368 int close_ctree(struct btrfs_root
*root
, struct btrfs_super_block
*s
)
371 struct btrfs_trans_handle
*trans
;
373 trans
= root
->fs_info
->running_transaction
;
374 btrfs_commit_transaction(trans
, root
, s
);
375 ret
= commit_tree_roots(trans
, root
->fs_info
);
377 ret
= __commit_transaction(trans
, root
);
379 write_ctree_super(trans
, root
, s
);
381 BUG_ON(!list_empty(&root
->fs_info
->trans
));
383 btrfs_free_block_groups(root
->fs_info
);
384 close(root
->fs_info
->fp
);
386 btrfs_block_release(root
, root
->node
);
387 if (root
->fs_info
->extent_root
->node
)
388 btrfs_block_release(root
->fs_info
->extent_root
,
389 root
->fs_info
->extent_root
->node
);
390 if (root
->fs_info
->tree_root
->node
)
391 btrfs_block_release(root
->fs_info
->tree_root
,
392 root
->fs_info
->tree_root
->node
);
393 btrfs_block_release(root
, root
->commit_root
);
395 printf("on close %d blocks are allocated\n", allocated_blocks
);
399 void btrfs_block_release(struct btrfs_root
*root
, struct btrfs_buffer
*buf
)
404 if (buf
->count
== 0) {
405 BUG_ON(!list_empty(&buf
->cache
));
406 BUG_ON(!list_empty(&buf
->dirty
));
407 if (!radix_tree_lookup(&root
->fs_info
->cache_radix
,
410 radix_tree_delete(&root
->fs_info
->cache_radix
, buf
->blocknr
);
411 memset(buf
, 0, sizeof(*buf
));
413 BUG_ON(allocated_blocks
== 0);
415 BUG_ON(root
->fs_info
->cache_size
== 0);
416 root
->fs_info
->cache_size
--;