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--;