diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-03-22 12:13:20 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@hera.kernel.org> | 2007-03-22 12:13:20 -0400 |
commit | e20d96d64f9cf9288ffecc9ad4714e91c3b97ca8 (patch) | |
tree | fbe07d48bc7997226075169118ffa2a2e63f5d51 /fs | |
parent | 2e635a278354a1a7951e16cfea4c247d6d0e7c99 (diff) |
Mountable btrfs, with readdir
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/btrfs/Makefile | 5 | ||||
-rw-r--r-- | fs/btrfs/ctree.c | 273 | ||||
-rw-r--r-- | fs/btrfs/ctree.h | 62 | ||||
-rw-r--r-- | fs/btrfs/dir-item.c | 17 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 281 | ||||
-rw-r--r-- | fs/btrfs/disk-io.h | 51 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 144 | ||||
-rw-r--r-- | fs/btrfs/hash.c | 9 | ||||
-rw-r--r-- | fs/btrfs/inode-map.c | 8 | ||||
-rw-r--r-- | fs/btrfs/print-tree.c | 20 | ||||
-rw-r--r-- | fs/btrfs/print-tree.h | 2 | ||||
-rw-r--r-- | fs/btrfs/root-tree.c | 4 | ||||
-rw-r--r-- | fs/btrfs/super.c | 261 | ||||
-rw-r--r-- | fs/btrfs/transaction.h | 4 |
14 files changed, 651 insertions, 490 deletions
diff --git a/fs/btrfs/Makefile b/fs/btrfs/Makefile index 99e45a54ebd6..1a0fb7422393 100644 --- a/fs/btrfs/Makefile +++ b/fs/btrfs/Makefile | |||
@@ -2,7 +2,8 @@ ifneq ($(KERNELRELEASE),) | |||
2 | # kbuild part of makefile | 2 | # kbuild part of makefile |
3 | 3 | ||
4 | obj-m := btrfs.o | 4 | obj-m := btrfs.o |
5 | btrfs-y := super.o | 5 | btrfs-y := super.o ctree.o extent-tree.o print-tree.o root-tree.o dir-item.o \ |
6 | hash.o file-item.o inode-item.o inode-map.o disk-io.o | ||
6 | 7 | ||
7 | #btrfs-y := ctree.o disk-io.o radix-tree.o extent-tree.o print-tree.o \ | 8 | #btrfs-y := ctree.o disk-io.o radix-tree.o extent-tree.o print-tree.o \ |
8 | # root-tree.o dir-item.o hash.o file-item.o inode-item.o \ | 9 | # root-tree.o dir-item.o hash.o file-item.o inode-item.o \ |
@@ -14,7 +15,7 @@ else | |||
14 | 15 | ||
15 | KERNELDIR := /lib/modules/`uname -r`/build | 16 | KERNELDIR := /lib/modules/`uname -r`/build |
16 | all:: | 17 | all:: |
17 | $(MAKE) -C $(KERNELDIR) M=`pwd` modules | 18 | $(MAKE) C=1 -C $(KERNELDIR) M=`pwd` modules |
18 | clean:: | 19 | clean:: |
19 | rm *.o btrfs.ko | 20 | rm *.o btrfs.ko |
20 | endif | 21 | endif |
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 9fbd07c37fde..e690e2bb47d2 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
@@ -7,11 +7,11 @@ static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root | |||
7 | static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root | 7 | static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root |
8 | *root, struct btrfs_path *path, int data_size); | 8 | *root, struct btrfs_path *path, int data_size); |
9 | static int push_node_left(struct btrfs_trans_handle *trans, struct btrfs_root | 9 | static int push_node_left(struct btrfs_trans_handle *trans, struct btrfs_root |
10 | *root, struct btrfs_buffer *dst, struct btrfs_buffer | 10 | *root, struct buffer_head *dst, struct buffer_head |
11 | *src); | 11 | *src); |
12 | static int balance_node_right(struct btrfs_trans_handle *trans, struct | 12 | static int balance_node_right(struct btrfs_trans_handle *trans, struct |
13 | btrfs_root *root, struct btrfs_buffer *dst_buf, | 13 | btrfs_root *root, struct buffer_head *dst_buf, |
14 | struct btrfs_buffer *src_buf); | 14 | struct buffer_head *src_buf); |
15 | static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 15 | static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
16 | struct btrfs_path *path, int level, int slot); | 16 | struct btrfs_path *path, int level, int slot); |
17 | 17 | ||
@@ -32,32 +32,34 @@ void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p) | |||
32 | } | 32 | } |
33 | 33 | ||
34 | static int btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root | 34 | static int btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root |
35 | *root, struct btrfs_buffer *buf, struct btrfs_buffer | 35 | *root, struct buffer_head *buf, struct buffer_head |
36 | *parent, int parent_slot, struct btrfs_buffer | 36 | *parent, int parent_slot, struct buffer_head |
37 | **cow_ret) | 37 | **cow_ret) |
38 | { | 38 | { |
39 | struct btrfs_buffer *cow; | 39 | struct buffer_head *cow; |
40 | struct btrfs_node *cow_node; | ||
40 | 41 | ||
41 | if (!list_empty(&buf->dirty)) { | 42 | if (!buffer_dirty(buf)) { |
42 | *cow_ret = buf; | 43 | *cow_ret = buf; |
43 | return 0; | 44 | return 0; |
44 | } | 45 | } |
45 | cow = btrfs_alloc_free_block(trans, root); | 46 | cow = btrfs_alloc_free_block(trans, root); |
46 | memcpy(&cow->node, &buf->node, root->blocksize); | 47 | cow_node = btrfs_buffer_node(cow); |
47 | btrfs_set_header_blocknr(&cow->node.header, cow->blocknr); | 48 | memcpy(cow_node, btrfs_buffer_node(buf), root->blocksize); |
49 | btrfs_set_header_blocknr(&cow_node->header, cow->b_blocknr); | ||
48 | *cow_ret = cow; | 50 | *cow_ret = cow; |
49 | btrfs_inc_ref(trans, root, buf); | 51 | btrfs_inc_ref(trans, root, buf); |
50 | if (buf == root->node) { | 52 | if (buf == root->node) { |
51 | root->node = cow; | 53 | root->node = cow; |
52 | cow->count++; | 54 | get_bh(cow); |
53 | if (buf != root->commit_root) | 55 | if (buf != root->commit_root) |
54 | btrfs_free_extent(trans, root, buf->blocknr, 1, 1); | 56 | btrfs_free_extent(trans, root, buf->b_blocknr, 1, 1); |
55 | btrfs_block_release(root, buf); | 57 | btrfs_block_release(root, buf); |
56 | } else { | 58 | } else { |
57 | btrfs_set_node_blockptr(&parent->node, parent_slot, | 59 | btrfs_set_node_blockptr(btrfs_buffer_node(parent), parent_slot, |
58 | cow->blocknr); | 60 | cow->b_blocknr); |
59 | BUG_ON(list_empty(&parent->dirty)); | 61 | BUG_ON(!buffer_dirty(parent)); |
60 | btrfs_free_extent(trans, root, buf->blocknr, 1, 1); | 62 | btrfs_free_extent(trans, root, buf->b_blocknr, 1, 1); |
61 | } | 63 | } |
62 | btrfs_block_release(root, buf); | 64 | btrfs_block_release(root, buf); |
63 | return 0; | 65 | return 0; |
@@ -119,12 +121,12 @@ static int check_node(struct btrfs_root *root, struct btrfs_path *path, | |||
119 | { | 121 | { |
120 | int i; | 122 | int i; |
121 | struct btrfs_node *parent = NULL; | 123 | struct btrfs_node *parent = NULL; |
122 | struct btrfs_node *node = &path->nodes[level]->node; | 124 | struct btrfs_node *node = btrfs_buffer_node(path->nodes[level]); |
123 | int parent_slot; | 125 | int parent_slot; |
124 | u32 nritems = btrfs_header_nritems(&node->header); | 126 | u32 nritems = btrfs_header_nritems(&node->header); |
125 | 127 | ||
126 | if (path->nodes[level + 1]) | 128 | if (path->nodes[level + 1]) |
127 | parent = &path->nodes[level + 1]->node; | 129 | parent = btrfs_buffer_node(path->nodes[level + 1]); |
128 | parent_slot = path->slots[level + 1]; | 130 | parent_slot = path->slots[level + 1]; |
129 | BUG_ON(nritems == 0); | 131 | BUG_ON(nritems == 0); |
130 | if (parent) { | 132 | if (parent) { |
@@ -148,13 +150,13 @@ static int check_leaf(struct btrfs_root *root, struct btrfs_path *path, | |||
148 | int level) | 150 | int level) |
149 | { | 151 | { |
150 | int i; | 152 | int i; |
151 | struct btrfs_leaf *leaf = &path->nodes[level]->leaf; | 153 | struct btrfs_leaf *leaf = btrfs_buffer_leaf(path->nodes[level]); |
152 | struct btrfs_node *parent = NULL; | 154 | struct btrfs_node *parent = NULL; |
153 | int parent_slot; | 155 | int parent_slot; |
154 | u32 nritems = btrfs_header_nritems(&leaf->header); | 156 | u32 nritems = btrfs_header_nritems(&leaf->header); |
155 | 157 | ||
156 | if (path->nodes[level + 1]) | 158 | if (path->nodes[level + 1]) |
157 | parent = &path->nodes[level + 1]->node; | 159 | parent = btrfs_buffer_node(path->nodes[level + 1]); |
158 | parent_slot = path->slots[level + 1]; | 160 | parent_slot = path->slots[level + 1]; |
159 | BUG_ON(btrfs_leaf_free_space(root, leaf) < 0); | 161 | BUG_ON(btrfs_leaf_free_space(root, leaf) < 0); |
160 | 162 | ||
@@ -250,11 +252,11 @@ static int bin_search(struct btrfs_node *c, struct btrfs_key *key, int *slot) | |||
250 | return -1; | 252 | return -1; |
251 | } | 253 | } |
252 | 254 | ||
253 | static struct btrfs_buffer *read_node_slot(struct btrfs_root *root, | 255 | static struct buffer_head *read_node_slot(struct btrfs_root *root, |
254 | struct btrfs_buffer *parent_buf, | 256 | struct buffer_head *parent_buf, |
255 | int slot) | 257 | int slot) |
256 | { | 258 | { |
257 | struct btrfs_node *node = &parent_buf->node; | 259 | struct btrfs_node *node = btrfs_buffer_node(parent_buf); |
258 | if (slot < 0) | 260 | if (slot < 0) |
259 | return NULL; | 261 | return NULL; |
260 | if (slot >= btrfs_header_nritems(&node->header)) | 262 | if (slot >= btrfs_header_nritems(&node->header)) |
@@ -265,10 +267,10 @@ static struct btrfs_buffer *read_node_slot(struct btrfs_root *root, | |||
265 | static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root | 267 | static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root |
266 | *root, struct btrfs_path *path, int level) | 268 | *root, struct btrfs_path *path, int level) |
267 | { | 269 | { |
268 | struct btrfs_buffer *right_buf; | 270 | struct buffer_head *right_buf; |
269 | struct btrfs_buffer *mid_buf; | 271 | struct buffer_head *mid_buf; |
270 | struct btrfs_buffer *left_buf; | 272 | struct buffer_head *left_buf; |
271 | struct btrfs_buffer *parent_buf = NULL; | 273 | struct buffer_head *parent_buf = NULL; |
272 | struct btrfs_node *right = NULL; | 274 | struct btrfs_node *right = NULL; |
273 | struct btrfs_node *mid; | 275 | struct btrfs_node *mid; |
274 | struct btrfs_node *left = NULL; | 276 | struct btrfs_node *left = NULL; |
@@ -283,7 +285,7 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root | |||
283 | return 0; | 285 | return 0; |
284 | 286 | ||
285 | mid_buf = path->nodes[level]; | 287 | mid_buf = path->nodes[level]; |
286 | mid = &mid_buf->node; | 288 | mid = btrfs_buffer_node(mid_buf); |
287 | orig_ptr = btrfs_node_blockptr(mid, orig_slot); | 289 | orig_ptr = btrfs_node_blockptr(mid, orig_slot); |
288 | 290 | ||
289 | if (level < BTRFS_MAX_LEVEL - 1) | 291 | if (level < BTRFS_MAX_LEVEL - 1) |
@@ -295,8 +297,8 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root | |||
295 | * by promoting the node below to a root | 297 | * by promoting the node below to a root |
296 | */ | 298 | */ |
297 | if (!parent_buf) { | 299 | if (!parent_buf) { |
298 | struct btrfs_buffer *child; | 300 | struct buffer_head *child; |
299 | u64 blocknr = mid_buf->blocknr; | 301 | u64 blocknr = mid_buf->b_blocknr; |
300 | 302 | ||
301 | if (btrfs_header_nritems(&mid->header) != 1) | 303 | if (btrfs_header_nritems(&mid->header) != 1) |
302 | return 0; | 304 | return 0; |
@@ -313,7 +315,7 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root | |||
313 | clean_tree_block(trans, root, mid_buf); | 315 | clean_tree_block(trans, root, mid_buf); |
314 | return btrfs_free_extent(trans, root, blocknr, 1, 1); | 316 | return btrfs_free_extent(trans, root, blocknr, 1, 1); |
315 | } | 317 | } |
316 | parent = &parent_buf->node; | 318 | parent = btrfs_buffer_node(parent_buf); |
317 | 319 | ||
318 | if (btrfs_header_nritems(&mid->header) > | 320 | if (btrfs_header_nritems(&mid->header) > |
319 | BTRFS_NODEPTRS_PER_BLOCK(root) / 4) | 321 | BTRFS_NODEPTRS_PER_BLOCK(root) / 4) |
@@ -326,7 +328,7 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root | |||
326 | if (left_buf) { | 328 | if (left_buf) { |
327 | btrfs_cow_block(trans, root, left_buf, parent_buf, pslot - 1, | 329 | btrfs_cow_block(trans, root, left_buf, parent_buf, pslot - 1, |
328 | &left_buf); | 330 | &left_buf); |
329 | left = &left_buf->node; | 331 | left = btrfs_buffer_node(left_buf); |
330 | orig_slot += btrfs_header_nritems(&left->header); | 332 | orig_slot += btrfs_header_nritems(&left->header); |
331 | wret = push_node_left(trans, root, left_buf, mid_buf); | 333 | wret = push_node_left(trans, root, left_buf, mid_buf); |
332 | if (wret < 0) | 334 | if (wret < 0) |
@@ -339,12 +341,12 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root | |||
339 | if (right_buf) { | 341 | if (right_buf) { |
340 | btrfs_cow_block(trans, root, right_buf, parent_buf, pslot + 1, | 342 | btrfs_cow_block(trans, root, right_buf, parent_buf, pslot + 1, |
341 | &right_buf); | 343 | &right_buf); |
342 | right = &right_buf->node; | 344 | right = btrfs_buffer_node(right_buf); |
343 | wret = push_node_left(trans, root, mid_buf, right_buf); | 345 | wret = push_node_left(trans, root, mid_buf, right_buf); |
344 | if (wret < 0) | 346 | if (wret < 0) |
345 | ret = wret; | 347 | ret = wret; |
346 | if (btrfs_header_nritems(&right->header) == 0) { | 348 | if (btrfs_header_nritems(&right->header) == 0) { |
347 | u64 blocknr = right_buf->blocknr; | 349 | u64 blocknr = right_buf->b_blocknr; |
348 | btrfs_block_release(root, right_buf); | 350 | btrfs_block_release(root, right_buf); |
349 | clean_tree_block(trans, root, right_buf); | 351 | clean_tree_block(trans, root, right_buf); |
350 | right_buf = NULL; | 352 | right_buf = NULL; |
@@ -360,7 +362,7 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root | |||
360 | memcpy(&parent->ptrs[pslot + 1].key, | 362 | memcpy(&parent->ptrs[pslot + 1].key, |
361 | &right->ptrs[0].key, | 363 | &right->ptrs[0].key, |
362 | sizeof(struct btrfs_disk_key)); | 364 | sizeof(struct btrfs_disk_key)); |
363 | BUG_ON(list_empty(&parent_buf->dirty)); | 365 | BUG_ON(!buffer_dirty(parent_buf)); |
364 | } | 366 | } |
365 | } | 367 | } |
366 | if (btrfs_header_nritems(&mid->header) == 1) { | 368 | if (btrfs_header_nritems(&mid->header) == 1) { |
@@ -381,7 +383,7 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root | |||
381 | } | 383 | } |
382 | if (btrfs_header_nritems(&mid->header) == 0) { | 384 | if (btrfs_header_nritems(&mid->header) == 0) { |
383 | /* we've managed to empty the middle node, drop it */ | 385 | /* we've managed to empty the middle node, drop it */ |
384 | u64 blocknr = mid_buf->blocknr; | 386 | u64 blocknr = mid_buf->b_blocknr; |
385 | btrfs_block_release(root, mid_buf); | 387 | btrfs_block_release(root, mid_buf); |
386 | clean_tree_block(trans, root, mid_buf); | 388 | clean_tree_block(trans, root, mid_buf); |
387 | mid_buf = NULL; | 389 | mid_buf = NULL; |
@@ -396,13 +398,13 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root | |||
396 | /* update the parent key to reflect our changes */ | 398 | /* update the parent key to reflect our changes */ |
397 | memcpy(&parent->ptrs[pslot].key, &mid->ptrs[0].key, | 399 | memcpy(&parent->ptrs[pslot].key, &mid->ptrs[0].key, |
398 | sizeof(struct btrfs_disk_key)); | 400 | sizeof(struct btrfs_disk_key)); |
399 | BUG_ON(list_empty(&parent_buf->dirty)); | 401 | BUG_ON(!buffer_dirty(parent_buf)); |
400 | } | 402 | } |
401 | 403 | ||
402 | /* update the path */ | 404 | /* update the path */ |
403 | if (left_buf) { | 405 | if (left_buf) { |
404 | if (btrfs_header_nritems(&left->header) > orig_slot) { | 406 | if (btrfs_header_nritems(&left->header) > orig_slot) { |
405 | left_buf->count++; // released below | 407 | get_bh(left_buf); |
406 | path->nodes[level] = left_buf; | 408 | path->nodes[level] = left_buf; |
407 | path->slots[level + 1] -= 1; | 409 | path->slots[level + 1] -= 1; |
408 | path->slots[level] = orig_slot; | 410 | path->slots[level] = orig_slot; |
@@ -415,8 +417,9 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root | |||
415 | } | 417 | } |
416 | /* double check we haven't messed things up */ | 418 | /* double check we haven't messed things up */ |
417 | check_block(root, path, level); | 419 | check_block(root, path, level); |
418 | if (orig_ptr != btrfs_node_blockptr(&path->nodes[level]->node, | 420 | if (orig_ptr != |
419 | path->slots[level])) | 421 | btrfs_node_blockptr(btrfs_buffer_node(path->nodes[level]), |
422 | path->slots[level])) | ||
420 | BUG(); | 423 | BUG(); |
421 | 424 | ||
422 | if (right_buf) | 425 | if (right_buf) |
@@ -443,8 +446,8 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root | |||
443 | *root, struct btrfs_key *key, struct btrfs_path *p, int | 446 | *root, struct btrfs_key *key, struct btrfs_path *p, int |
444 | ins_len, int cow) | 447 | ins_len, int cow) |
445 | { | 448 | { |
446 | struct btrfs_buffer *b; | 449 | struct buffer_head *b; |
447 | struct btrfs_buffer *cow_buf; | 450 | struct buffer_head *cow_buf; |
448 | struct btrfs_node *c; | 451 | struct btrfs_node *c; |
449 | int slot; | 452 | int slot; |
450 | int ret; | 453 | int ret; |
@@ -452,18 +455,20 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root | |||
452 | 455 | ||
453 | again: | 456 | again: |
454 | b = root->node; | 457 | b = root->node; |
455 | b->count++; | 458 | get_bh(b); |
456 | while (b) { | 459 | while (b) { |
457 | level = btrfs_header_level(&b->node.header); | 460 | c = btrfs_buffer_node(b); |
461 | level = btrfs_header_level(&c->header); | ||
458 | if (cow) { | 462 | if (cow) { |
459 | int wret; | 463 | int wret; |
460 | wret = btrfs_cow_block(trans, root, b, p->nodes[level + | 464 | wret = btrfs_cow_block(trans, root, b, |
461 | 1], p->slots[level + 1], | 465 | p->nodes[level + 1], |
466 | p->slots[level + 1], | ||
462 | &cow_buf); | 467 | &cow_buf); |
463 | b = cow_buf; | 468 | b = cow_buf; |
464 | } | 469 | } |
465 | BUG_ON(!cow && ins_len); | 470 | BUG_ON(!cow && ins_len); |
466 | c = &b->node; | 471 | c = btrfs_buffer_node(b); |
467 | p->nodes[level] = b; | 472 | p->nodes[level] = b; |
468 | ret = check_block(root, p, level); | 473 | ret = check_block(root, p, level); |
469 | if (ret) | 474 | if (ret) |
@@ -480,7 +485,7 @@ again: | |||
480 | if (sret) | 485 | if (sret) |
481 | return sret; | 486 | return sret; |
482 | b = p->nodes[level]; | 487 | b = p->nodes[level]; |
483 | c = &b->node; | 488 | c = btrfs_buffer_node(b); |
484 | slot = p->slots[level]; | 489 | slot = p->slots[level]; |
485 | } else if (ins_len < 0) { | 490 | } else if (ins_len < 0) { |
486 | int sret = balance_level(trans, root, p, | 491 | int sret = balance_level(trans, root, p, |
@@ -490,7 +495,7 @@ again: | |||
490 | b = p->nodes[level]; | 495 | b = p->nodes[level]; |
491 | if (!b) | 496 | if (!b) |
492 | goto again; | 497 | goto again; |
493 | c = &b->node; | 498 | c = btrfs_buffer_node(b); |
494 | slot = p->slots[level]; | 499 | slot = p->slots[level]; |
495 | BUG_ON(btrfs_header_nritems(&c->header) == 1); | 500 | BUG_ON(btrfs_header_nritems(&c->header) == 1); |
496 | } | 501 | } |
@@ -505,11 +510,9 @@ again: | |||
505 | if (sret) | 510 | if (sret) |
506 | return sret; | 511 | return sret; |
507 | } | 512 | } |
508 | BUG_ON(root->node->count == 1); | ||
509 | return ret; | 513 | return ret; |
510 | } | 514 | } |
511 | } | 515 | } |
512 | BUG_ON(root->node->count == 1); | ||
513 | return 1; | 516 | return 1; |
514 | } | 517 | } |
515 | 518 | ||
@@ -534,9 +537,9 @@ static int fixup_low_keys(struct btrfs_trans_handle *trans, struct btrfs_root | |||
534 | int tslot = path->slots[i]; | 537 | int tslot = path->slots[i]; |
535 | if (!path->nodes[i]) | 538 | if (!path->nodes[i]) |
536 | break; | 539 | break; |
537 | t = &path->nodes[i]->node; | 540 | t = btrfs_buffer_node(path->nodes[i]); |
538 | memcpy(&t->ptrs[tslot].key, key, sizeof(*key)); | 541 | memcpy(&t->ptrs[tslot].key, key, sizeof(*key)); |
539 | BUG_ON(list_empty(&path->nodes[i]->dirty)); | 542 | BUG_ON(!buffer_dirty(path->nodes[i])); |
540 | if (tslot != 0) | 543 | if (tslot != 0) |
541 | break; | 544 | break; |
542 | } | 545 | } |
@@ -551,11 +554,11 @@ static int fixup_low_keys(struct btrfs_trans_handle *trans, struct btrfs_root | |||
551 | * error, and > 0 if there was no room in the left hand block. | 554 | * error, and > 0 if there was no room in the left hand block. |
552 | */ | 555 | */ |
553 | static int push_node_left(struct btrfs_trans_handle *trans, struct btrfs_root | 556 | static int push_node_left(struct btrfs_trans_handle *trans, struct btrfs_root |
554 | *root, struct btrfs_buffer *dst_buf, struct | 557 | *root, struct buffer_head *dst_buf, struct |
555 | btrfs_buffer *src_buf) | 558 | buffer_head *src_buf) |
556 | { | 559 | { |
557 | struct btrfs_node *src = &src_buf->node; | 560 | struct btrfs_node *src = btrfs_buffer_node(src_buf); |
558 | struct btrfs_node *dst = &dst_buf->node; | 561 | struct btrfs_node *dst = btrfs_buffer_node(dst_buf); |
559 | int push_items = 0; | 562 | int push_items = 0; |
560 | int src_nritems; | 563 | int src_nritems; |
561 | int dst_nritems; | 564 | int dst_nritems; |
@@ -580,8 +583,8 @@ static int push_node_left(struct btrfs_trans_handle *trans, struct btrfs_root | |||
580 | } | 583 | } |
581 | btrfs_set_header_nritems(&src->header, src_nritems - push_items); | 584 | btrfs_set_header_nritems(&src->header, src_nritems - push_items); |
582 | btrfs_set_header_nritems(&dst->header, dst_nritems + push_items); | 585 | btrfs_set_header_nritems(&dst->header, dst_nritems + push_items); |
583 | BUG_ON(list_empty(&src_buf->dirty)); | 586 | BUG_ON(!buffer_dirty(src_buf)); |
584 | BUG_ON(list_empty(&dst_buf->dirty)); | 587 | BUG_ON(!buffer_dirty(dst_buf)); |
585 | return ret; | 588 | return ret; |
586 | } | 589 | } |
587 | 590 | ||
@@ -595,11 +598,11 @@ static int push_node_left(struct btrfs_trans_handle *trans, struct btrfs_root | |||
595 | * this will only push up to 1/2 the contents of the left node over | 598 | * this will only push up to 1/2 the contents of the left node over |
596 | */ | 599 | */ |
597 | static int balance_node_right(struct btrfs_trans_handle *trans, struct | 600 | static int balance_node_right(struct btrfs_trans_handle *trans, struct |
598 | btrfs_root *root, struct btrfs_buffer *dst_buf, | 601 | btrfs_root *root, struct buffer_head *dst_buf, |
599 | struct btrfs_buffer *src_buf) | 602 | struct buffer_head *src_buf) |
600 | { | 603 | { |
601 | struct btrfs_node *src = &src_buf->node; | 604 | struct btrfs_node *src = btrfs_buffer_node(src_buf); |
602 | struct btrfs_node *dst = &dst_buf->node; | 605 | struct btrfs_node *dst = btrfs_buffer_node(dst_buf); |
603 | int push_items = 0; | 606 | int push_items = 0; |
604 | int max_push; | 607 | int max_push; |
605 | int src_nritems; | 608 | int src_nritems; |
@@ -628,8 +631,8 @@ static int balance_node_right(struct btrfs_trans_handle *trans, struct | |||
628 | btrfs_set_header_nritems(&src->header, src_nritems - push_items); | 631 | btrfs_set_header_nritems(&src->header, src_nritems - push_items); |
629 | btrfs_set_header_nritems(&dst->header, dst_nritems + push_items); | 632 | btrfs_set_header_nritems(&dst->header, dst_nritems + push_items); |
630 | 633 | ||
631 | BUG_ON(list_empty(&src_buf->dirty)); | 634 | BUG_ON(!buffer_dirty(src_buf)); |
632 | BUG_ON(list_empty(&dst_buf->dirty)); | 635 | BUG_ON(!buffer_dirty(dst_buf)); |
633 | return ret; | 636 | return ret; |
634 | } | 637 | } |
635 | 638 | ||
@@ -643,7 +646,7 @@ static int balance_node_right(struct btrfs_trans_handle *trans, struct | |||
643 | static int insert_new_root(struct btrfs_trans_handle *trans, struct btrfs_root | 646 | static int insert_new_root(struct btrfs_trans_handle *trans, struct btrfs_root |
644 | *root, struct btrfs_path *path, int level) | 647 | *root, struct btrfs_path *path, int level) |
645 | { | 648 | { |
646 | struct btrfs_buffer *t; | 649 | struct buffer_head *t; |
647 | struct btrfs_node *lower; | 650 | struct btrfs_node *lower; |
648 | struct btrfs_node *c; | 651 | struct btrfs_node *c; |
649 | struct btrfs_disk_key *lower_key; | 652 | struct btrfs_disk_key *lower_key; |
@@ -652,24 +655,24 @@ static int insert_new_root(struct btrfs_trans_handle *trans, struct btrfs_root | |||
652 | BUG_ON(path->nodes[level-1] != root->node); | 655 | BUG_ON(path->nodes[level-1] != root->node); |
653 | 656 | ||
654 | t = btrfs_alloc_free_block(trans, root); | 657 | t = btrfs_alloc_free_block(trans, root); |
655 | c = &t->node; | 658 | c = btrfs_buffer_node(t); |
656 | memset(c, 0, root->blocksize); | 659 | memset(c, 0, root->blocksize); |
657 | btrfs_set_header_nritems(&c->header, 1); | 660 | btrfs_set_header_nritems(&c->header, 1); |
658 | btrfs_set_header_level(&c->header, level); | 661 | btrfs_set_header_level(&c->header, level); |
659 | btrfs_set_header_blocknr(&c->header, t->blocknr); | 662 | btrfs_set_header_blocknr(&c->header, t->b_blocknr); |
660 | btrfs_set_header_parentid(&c->header, | 663 | btrfs_set_header_parentid(&c->header, |
661 | btrfs_header_parentid(&root->node->node.header)); | 664 | btrfs_header_parentid(btrfs_buffer_header(root->node))); |
662 | lower = &path->nodes[level-1]->node; | 665 | lower = btrfs_buffer_node(path->nodes[level-1]); |
663 | if (btrfs_is_leaf(lower)) | 666 | if (btrfs_is_leaf(lower)) |
664 | lower_key = &((struct btrfs_leaf *)lower)->items[0].key; | 667 | lower_key = &((struct btrfs_leaf *)lower)->items[0].key; |
665 | else | 668 | else |
666 | lower_key = &lower->ptrs[0].key; | 669 | lower_key = &lower->ptrs[0].key; |
667 | memcpy(&c->ptrs[0].key, lower_key, sizeof(struct btrfs_disk_key)); | 670 | memcpy(&c->ptrs[0].key, lower_key, sizeof(struct btrfs_disk_key)); |
668 | btrfs_set_node_blockptr(c, 0, path->nodes[level - 1]->blocknr); | 671 | btrfs_set_node_blockptr(c, 0, path->nodes[level - 1]->b_blocknr); |
669 | /* the super has an extra ref to root->node */ | 672 | /* the super has an extra ref to root->node */ |
670 | btrfs_block_release(root, root->node); | 673 | btrfs_block_release(root, root->node); |
671 | root->node = t; | 674 | root->node = t; |
672 | t->count++; | 675 | get_bh(t); |
673 | path->nodes[level] = t; | 676 | path->nodes[level] = t; |
674 | path->slots[level] = 0; | 677 | path->slots[level] = 0; |
675 | return 0; | 678 | return 0; |
@@ -692,7 +695,7 @@ static int insert_ptr(struct btrfs_trans_handle *trans, struct btrfs_root | |||
692 | int nritems; | 695 | int nritems; |
693 | 696 | ||
694 | BUG_ON(!path->nodes[level]); | 697 | BUG_ON(!path->nodes[level]); |
695 | lower = &path->nodes[level]->node; | 698 | lower = btrfs_buffer_node(path->nodes[level]); |
696 | nritems = btrfs_header_nritems(&lower->header); | 699 | nritems = btrfs_header_nritems(&lower->header); |
697 | if (slot > nritems) | 700 | if (slot > nritems) |
698 | BUG(); | 701 | BUG(); |
@@ -705,7 +708,7 @@ static int insert_ptr(struct btrfs_trans_handle *trans, struct btrfs_root | |||
705 | memcpy(&lower->ptrs[slot].key, key, sizeof(struct btrfs_disk_key)); | 708 | memcpy(&lower->ptrs[slot].key, key, sizeof(struct btrfs_disk_key)); |
706 | btrfs_set_node_blockptr(lower, slot, blocknr); | 709 | btrfs_set_node_blockptr(lower, slot, blocknr); |
707 | btrfs_set_header_nritems(&lower->header, nritems + 1); | 710 | btrfs_set_header_nritems(&lower->header, nritems + 1); |
708 | BUG_ON(list_empty(&path->nodes[level]->dirty)); | 711 | BUG_ON(!buffer_dirty(path->nodes[level])); |
709 | return 0; | 712 | return 0; |
710 | } | 713 | } |
711 | 714 | ||
@@ -721,9 +724,9 @@ static int insert_ptr(struct btrfs_trans_handle *trans, struct btrfs_root | |||
721 | static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root | 724 | static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root |
722 | *root, struct btrfs_path *path, int level) | 725 | *root, struct btrfs_path *path, int level) |
723 | { | 726 | { |
724 | struct btrfs_buffer *t; | 727 | struct buffer_head *t; |
725 | struct btrfs_node *c; | 728 | struct btrfs_node *c; |
726 | struct btrfs_buffer *split_buffer; | 729 | struct buffer_head *split_buffer; |
727 | struct btrfs_node *split; | 730 | struct btrfs_node *split; |
728 | int mid; | 731 | int mid; |
729 | int ret; | 732 | int ret; |
@@ -731,7 +734,7 @@ static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root | |||
731 | u32 c_nritems; | 734 | u32 c_nritems; |
732 | 735 | ||
733 | t = path->nodes[level]; | 736 | t = path->nodes[level]; |
734 | c = &t->node; | 737 | c = btrfs_buffer_node(t); |
735 | if (t == root->node) { | 738 | if (t == root->node) { |
736 | /* trying to split the root, lets make a new one */ | 739 | /* trying to split the root, lets make a new one */ |
737 | ret = insert_new_root(trans, root, path, level + 1); | 740 | ret = insert_new_root(trans, root, path, level + 1); |
@@ -740,11 +743,11 @@ static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root | |||
740 | } | 743 | } |
741 | c_nritems = btrfs_header_nritems(&c->header); | 744 | c_nritems = btrfs_header_nritems(&c->header); |
742 | split_buffer = btrfs_alloc_free_block(trans, root); | 745 | split_buffer = btrfs_alloc_free_block(trans, root); |
743 | split = &split_buffer->node; | 746 | split = btrfs_buffer_node(split_buffer); |
744 | btrfs_set_header_flags(&split->header, btrfs_header_flags(&c->header)); | 747 | btrfs_set_header_flags(&split->header, btrfs_header_flags(&c->header)); |
745 | btrfs_set_header_blocknr(&split->header, split_buffer->blocknr); | 748 | btrfs_set_header_blocknr(&split->header, split_buffer->b_blocknr); |
746 | btrfs_set_header_parentid(&split->header, | 749 | btrfs_set_header_parentid(&split->header, |
747 | btrfs_header_parentid(&root->node->node.header)); | 750 | btrfs_header_parentid(btrfs_buffer_header(root->node))); |
748 | mid = (c_nritems + 1) / 2; | 751 | mid = (c_nritems + 1) / 2; |
749 | memcpy(split->ptrs, c->ptrs + mid, | 752 | memcpy(split->ptrs, c->ptrs + mid, |
750 | (c_nritems - mid) * sizeof(struct btrfs_key_ptr)); | 753 | (c_nritems - mid) * sizeof(struct btrfs_key_ptr)); |
@@ -752,9 +755,9 @@ static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root | |||
752 | btrfs_set_header_nritems(&c->header, mid); | 755 | btrfs_set_header_nritems(&c->header, mid); |
753 | ret = 0; | 756 | ret = 0; |
754 | 757 | ||
755 | BUG_ON(list_empty(&t->dirty)); | 758 | BUG_ON(!buffer_dirty(t)); |
756 | wret = insert_ptr(trans, root, path, &split->ptrs[0].key, | 759 | wret = insert_ptr(trans, root, path, &split->ptrs[0].key, |
757 | split_buffer->blocknr, path->slots[level + 1] + 1, | 760 | split_buffer->b_blocknr, path->slots[level + 1] + 1, |
758 | level + 1); | 761 | level + 1); |
759 | if (wret) | 762 | if (wret) |
760 | ret = wret; | 763 | ret = wret; |
@@ -798,11 +801,12 @@ static int leaf_space_used(struct btrfs_leaf *l, int start, int nr) | |||
798 | static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root | 801 | static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root |
799 | *root, struct btrfs_path *path, int data_size) | 802 | *root, struct btrfs_path *path, int data_size) |
800 | { | 803 | { |
801 | struct btrfs_buffer *left_buf = path->nodes[0]; | 804 | struct buffer_head *left_buf = path->nodes[0]; |
802 | struct btrfs_leaf *left = &left_buf->leaf; | 805 | struct btrfs_leaf *left = btrfs_buffer_leaf(left_buf); |
803 | struct btrfs_leaf *right; | 806 | struct btrfs_leaf *right; |
804 | struct btrfs_buffer *right_buf; | 807 | struct buffer_head *right_buf; |
805 | struct btrfs_buffer *upper; | 808 | struct buffer_head *upper; |
809 | struct btrfs_node *upper_node; | ||
806 | int slot; | 810 | int slot; |
807 | int i; | 811 | int i; |
808 | int free_space; | 812 | int free_space; |
@@ -817,12 +821,13 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root | |||
817 | return 1; | 821 | return 1; |
818 | } | 822 | } |
819 | upper = path->nodes[1]; | 823 | upper = path->nodes[1]; |
820 | if (slot >= btrfs_header_nritems(&upper->node.header) - 1) { | 824 | upper_node = btrfs_buffer_node(upper); |
825 | if (slot >= btrfs_header_nritems(&upper_node->header) - 1) { | ||
821 | return 1; | 826 | return 1; |
822 | } | 827 | } |
823 | right_buf = read_tree_block(root, btrfs_node_blockptr(&upper->node, | 828 | right_buf = read_tree_block(root, |
824 | slot + 1)); | 829 | btrfs_node_blockptr(btrfs_buffer_node(upper), slot + 1)); |
825 | right = &right_buf->leaf; | 830 | right = btrfs_buffer_leaf(right_buf); |
826 | free_space = btrfs_leaf_free_space(root, right); | 831 | free_space = btrfs_leaf_free_space(root, right); |
827 | if (free_space < data_size + sizeof(struct btrfs_item)) { | 832 | if (free_space < data_size + sizeof(struct btrfs_item)) { |
828 | btrfs_block_release(root, right_buf); | 833 | btrfs_block_release(root, right_buf); |
@@ -830,7 +835,7 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root | |||
830 | } | 835 | } |
831 | /* cow and double check */ | 836 | /* cow and double check */ |
832 | btrfs_cow_block(trans, root, right_buf, upper, slot + 1, &right_buf); | 837 | btrfs_cow_block(trans, root, right_buf, upper, slot + 1, &right_buf); |
833 | right = &right_buf->leaf; | 838 | right = btrfs_buffer_leaf(right_buf); |
834 | free_space = btrfs_leaf_free_space(root, right); | 839 | free_space = btrfs_leaf_free_space(root, right); |
835 | if (free_space < data_size + sizeof(struct btrfs_item)) { | 840 | if (free_space < data_size + sizeof(struct btrfs_item)) { |
836 | btrfs_block_release(root, right_buf); | 841 | btrfs_block_release(root, right_buf); |
@@ -881,11 +886,11 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root | |||
881 | left_nritems -= push_items; | 886 | left_nritems -= push_items; |
882 | btrfs_set_header_nritems(&left->header, left_nritems); | 887 | btrfs_set_header_nritems(&left->header, left_nritems); |
883 | 888 | ||
884 | BUG_ON(list_empty(&left_buf->dirty)); | 889 | BUG_ON(!buffer_dirty(left_buf)); |
885 | BUG_ON(list_empty(&right_buf->dirty)); | 890 | BUG_ON(!buffer_dirty(right_buf)); |
886 | memcpy(&upper->node.ptrs[slot + 1].key, | 891 | memcpy(&upper_node->ptrs[slot + 1].key, |
887 | &right->items[0].key, sizeof(struct btrfs_disk_key)); | 892 | &right->items[0].key, sizeof(struct btrfs_disk_key)); |
888 | BUG_ON(list_empty(&upper->dirty)); | 893 | BUG_ON(!buffer_dirty(upper)); |
889 | 894 | ||
890 | /* then fixup the leaf pointer in the path */ | 895 | /* then fixup the leaf pointer in the path */ |
891 | if (path->slots[0] >= left_nritems) { | 896 | if (path->slots[0] >= left_nritems) { |
@@ -905,9 +910,9 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root | |||
905 | static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root | 910 | static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root |
906 | *root, struct btrfs_path *path, int data_size) | 911 | *root, struct btrfs_path *path, int data_size) |
907 | { | 912 | { |
908 | struct btrfs_buffer *right_buf = path->nodes[0]; | 913 | struct buffer_head *right_buf = path->nodes[0]; |
909 | struct btrfs_leaf *right = &right_buf->leaf; | 914 | struct btrfs_leaf *right = btrfs_buffer_leaf(right_buf); |
910 | struct btrfs_buffer *t; | 915 | struct buffer_head *t; |
911 | struct btrfs_leaf *left; | 916 | struct btrfs_leaf *left; |
912 | int slot; | 917 | int slot; |
913 | int i; | 918 | int i; |
@@ -926,9 +931,9 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root | |||
926 | if (!path->nodes[1]) { | 931 | if (!path->nodes[1]) { |
927 | return 1; | 932 | return 1; |
928 | } | 933 | } |
929 | t = read_tree_block(root, btrfs_node_blockptr(&path->nodes[1]->node, | 934 | t = read_tree_block(root, |
930 | slot - 1)); | 935 | btrfs_node_blockptr(btrfs_buffer_node(path->nodes[1]), slot - 1)); |
931 | left = &t->leaf; | 936 | left = btrfs_buffer_leaf(t); |
932 | free_space = btrfs_leaf_free_space(root, left); | 937 | free_space = btrfs_leaf_free_space(root, left); |
933 | if (free_space < data_size + sizeof(struct btrfs_item)) { | 938 | if (free_space < data_size + sizeof(struct btrfs_item)) { |
934 | btrfs_block_release(root, t); | 939 | btrfs_block_release(root, t); |
@@ -937,7 +942,7 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root | |||
937 | 942 | ||
938 | /* cow and double check */ | 943 | /* cow and double check */ |
939 | btrfs_cow_block(trans, root, t, path->nodes[1], slot - 1, &t); | 944 | btrfs_cow_block(trans, root, t, path->nodes[1], slot - 1, &t); |
940 | left = &t->leaf; | 945 | left = btrfs_buffer_leaf(t); |
941 | free_space = btrfs_leaf_free_space(root, left); | 946 | free_space = btrfs_leaf_free_space(root, left); |
942 | if (free_space < data_size + sizeof(struct btrfs_item)) { | 947 | if (free_space < data_size + sizeof(struct btrfs_item)) { |
943 | btrfs_block_release(root, t); | 948 | btrfs_block_release(root, t); |
@@ -999,8 +1004,8 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root | |||
999 | push_space = btrfs_item_offset(right->items + i); | 1004 | push_space = btrfs_item_offset(right->items + i); |
1000 | } | 1005 | } |
1001 | 1006 | ||
1002 | BUG_ON(list_empty(&t->dirty)); | 1007 | BUG_ON(!buffer_dirty(t)); |
1003 | BUG_ON(list_empty(&right_buf->dirty)); | 1008 | BUG_ON(!buffer_dirty(right_buf)); |
1004 | 1009 | ||
1005 | wret = fixup_low_keys(trans, root, path, &right->items[0].key, 1); | 1010 | wret = fixup_low_keys(trans, root, path, &right->items[0].key, 1); |
1006 | if (wret) | 1011 | if (wret) |
@@ -1029,13 +1034,13 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1029 | static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root | 1034 | static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root |
1030 | *root, struct btrfs_path *path, int data_size) | 1035 | *root, struct btrfs_path *path, int data_size) |
1031 | { | 1036 | { |
1032 | struct btrfs_buffer *l_buf; | 1037 | struct buffer_head *l_buf; |
1033 | struct btrfs_leaf *l; | 1038 | struct btrfs_leaf *l; |
1034 | u32 nritems; | 1039 | u32 nritems; |
1035 | int mid; | 1040 | int mid; |
1036 | int slot; | 1041 | int slot; |
1037 | struct btrfs_leaf *right; | 1042 | struct btrfs_leaf *right; |
1038 | struct btrfs_buffer *right_buffer; | 1043 | struct buffer_head *right_buffer; |
1039 | int space_needed = data_size + sizeof(struct btrfs_item); | 1044 | int space_needed = data_size + sizeof(struct btrfs_item); |
1040 | int data_copy_size; | 1045 | int data_copy_size; |
1041 | int rt_data_off; | 1046 | int rt_data_off; |
@@ -1053,7 +1058,7 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1053 | return wret; | 1058 | return wret; |
1054 | } | 1059 | } |
1055 | l_buf = path->nodes[0]; | 1060 | l_buf = path->nodes[0]; |
1056 | l = &l_buf->leaf; | 1061 | l = btrfs_buffer_leaf(l_buf); |
1057 | 1062 | ||
1058 | /* did the pushes work? */ | 1063 | /* did the pushes work? */ |
1059 | if (btrfs_leaf_free_space(root, l) >= | 1064 | if (btrfs_leaf_free_space(root, l) >= |
@@ -1071,7 +1076,7 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1071 | right_buffer = btrfs_alloc_free_block(trans, root); | 1076 | right_buffer = btrfs_alloc_free_block(trans, root); |
1072 | BUG_ON(!right_buffer); | 1077 | BUG_ON(!right_buffer); |
1073 | BUG_ON(mid == nritems); | 1078 | BUG_ON(mid == nritems); |
1074 | right = &right_buffer->leaf; | 1079 | right = btrfs_buffer_leaf(right_buffer); |
1075 | memset(&right->header, 0, sizeof(right->header)); | 1080 | memset(&right->header, 0, sizeof(right->header)); |
1076 | if (mid <= slot) { | 1081 | if (mid <= slot) { |
1077 | /* FIXME, just alloc a new leaf here */ | 1082 | /* FIXME, just alloc a new leaf here */ |
@@ -1085,10 +1090,10 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1085 | BUG(); | 1090 | BUG(); |
1086 | } | 1091 | } |
1087 | btrfs_set_header_nritems(&right->header, nritems - mid); | 1092 | btrfs_set_header_nritems(&right->header, nritems - mid); |
1088 | btrfs_set_header_blocknr(&right->header, right_buffer->blocknr); | 1093 | btrfs_set_header_blocknr(&right->header, right_buffer->b_blocknr); |
1089 | btrfs_set_header_level(&right->header, 0); | 1094 | btrfs_set_header_level(&right->header, 0); |
1090 | btrfs_set_header_parentid(&right->header, | 1095 | btrfs_set_header_parentid(&right->header, |
1091 | btrfs_header_parentid(&root->node->node.header)); | 1096 | btrfs_header_parentid(btrfs_buffer_header(root->node))); |
1092 | data_copy_size = btrfs_item_end(l->items + mid) - | 1097 | data_copy_size = btrfs_item_end(l->items + mid) - |
1093 | leaf_data_end(root, l); | 1098 | leaf_data_end(root, l); |
1094 | memcpy(right->items, l->items + mid, | 1099 | memcpy(right->items, l->items + mid, |
@@ -1107,11 +1112,11 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1107 | btrfs_set_header_nritems(&l->header, mid); | 1112 | btrfs_set_header_nritems(&l->header, mid); |
1108 | ret = 0; | 1113 | ret = 0; |
1109 | wret = insert_ptr(trans, root, path, &right->items[0].key, | 1114 | wret = insert_ptr(trans, root, path, &right->items[0].key, |
1110 | right_buffer->blocknr, path->slots[1] + 1, 1); | 1115 | right_buffer->b_blocknr, path->slots[1] + 1, 1); |
1111 | if (wret) | 1116 | if (wret) |
1112 | ret = wret; | 1117 | ret = wret; |
1113 | BUG_ON(list_empty(&right_buffer->dirty)); | 1118 | BUG_ON(!buffer_dirty(right_buffer)); |
1114 | BUG_ON(list_empty(&l_buf->dirty)); | 1119 | BUG_ON(!buffer_dirty(l_buf)); |
1115 | BUG_ON(path->slots[0] != slot); | 1120 | BUG_ON(path->slots[0] != slot); |
1116 | if (mid <= slot) { | 1121 | if (mid <= slot) { |
1117 | btrfs_block_release(root, path->nodes[0]); | 1122 | btrfs_block_release(root, path->nodes[0]); |
@@ -1136,7 +1141,7 @@ int btrfs_insert_empty_item(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1136 | int slot; | 1141 | int slot; |
1137 | int slot_orig; | 1142 | int slot_orig; |
1138 | struct btrfs_leaf *leaf; | 1143 | struct btrfs_leaf *leaf; |
1139 | struct btrfs_buffer *leaf_buf; | 1144 | struct buffer_head *leaf_buf; |
1140 | u32 nritems; | 1145 | u32 nritems; |
1141 | unsigned int data_end; | 1146 | unsigned int data_end; |
1142 | struct btrfs_disk_key disk_key; | 1147 | struct btrfs_disk_key disk_key; |
@@ -1156,7 +1161,7 @@ int btrfs_insert_empty_item(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1156 | 1161 | ||
1157 | slot_orig = path->slots[0]; | 1162 | slot_orig = path->slots[0]; |
1158 | leaf_buf = path->nodes[0]; | 1163 | leaf_buf = path->nodes[0]; |
1159 | leaf = &leaf_buf->leaf; | 1164 | leaf = btrfs_buffer_leaf(leaf_buf); |
1160 | 1165 | ||
1161 | nritems = btrfs_header_nritems(&leaf->header); | 1166 | nritems = btrfs_header_nritems(&leaf->header); |
1162 | data_end = leaf_data_end(root, leaf); | 1167 | data_end = leaf_data_end(root, leaf); |
@@ -1202,7 +1207,7 @@ int btrfs_insert_empty_item(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1202 | if (slot == 0) | 1207 | if (slot == 0) |
1203 | ret = fixup_low_keys(trans, root, path, &disk_key, 1); | 1208 | ret = fixup_low_keys(trans, root, path, &disk_key, 1); |
1204 | 1209 | ||
1205 | BUG_ON(list_empty(&leaf_buf->dirty)); | 1210 | BUG_ON(!buffer_dirty(leaf_buf)); |
1206 | if (btrfs_leaf_free_space(root, leaf) < 0) | 1211 | if (btrfs_leaf_free_space(root, leaf) < 0) |
1207 | BUG(); | 1212 | BUG(); |
1208 | check_leaf(root, path, 0); | 1213 | check_leaf(root, path, 0); |
@@ -1225,7 +1230,8 @@ int btrfs_insert_item(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1225 | btrfs_init_path(&path); | 1230 | btrfs_init_path(&path); |
1226 | ret = btrfs_insert_empty_item(trans, root, &path, cpu_key, data_size); | 1231 | ret = btrfs_insert_empty_item(trans, root, &path, cpu_key, data_size); |
1227 | if (!ret) { | 1232 | if (!ret) { |
1228 | ptr = btrfs_item_ptr(&path.nodes[0]->leaf, path.slots[0], u8); | 1233 | ptr = btrfs_item_ptr(btrfs_buffer_leaf(path.nodes[0]), |
1234 | path.slots[0], u8); | ||
1229 | memcpy(ptr, data, data_size); | 1235 | memcpy(ptr, data, data_size); |
1230 | } | 1236 | } |
1231 | btrfs_release_path(root, &path); | 1237 | btrfs_release_path(root, &path); |
@@ -1243,12 +1249,12 @@ static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
1243 | struct btrfs_path *path, int level, int slot) | 1249 | struct btrfs_path *path, int level, int slot) |
1244 | { | 1250 | { |
1245 | struct btrfs_node *node; | 1251 | struct btrfs_node *node; |
1246 | struct btrfs_buffer *parent = path->nodes[level]; | 1252 | struct buffer_head *parent = path->nodes[level]; |
1247 | u32 nritems; | 1253 | u32 nritems; |
1248 | int ret = 0; | 1254 | int ret = 0; |
1249 | int wret; | 1255 | int wret; |
1250 | 1256 | ||
1251 | node = &parent->node; | 1257 | node = btrfs_buffer_node(parent); |
1252 | nritems = btrfs_header_nritems(&node->header); | 1258 | nritems = btrfs_header_nritems(&node->header); |
1253 | if (slot != nritems -1) { | 1259 | if (slot != nritems -1) { |
1254 | memmove(node->ptrs + slot, node->ptrs + slot + 1, | 1260 | memmove(node->ptrs + slot, node->ptrs + slot + 1, |
@@ -1257,16 +1263,17 @@ static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
1257 | nritems--; | 1263 | nritems--; |
1258 | btrfs_set_header_nritems(&node->header, nritems); | 1264 | btrfs_set_header_nritems(&node->header, nritems); |
1259 | if (nritems == 0 && parent == root->node) { | 1265 | if (nritems == 0 && parent == root->node) { |
1260 | BUG_ON(btrfs_header_level(&root->node->node.header) != 1); | 1266 | struct btrfs_header *header = btrfs_buffer_header(root->node); |
1267 | BUG_ON(btrfs_header_level(header) != 1); | ||
1261 | /* just turn the root into a leaf and break */ | 1268 | /* just turn the root into a leaf and break */ |
1262 | btrfs_set_header_level(&root->node->node.header, 0); | 1269 | btrfs_set_header_level(header, 0); |
1263 | } else if (slot == 0) { | 1270 | } else if (slot == 0) { |
1264 | wret = fixup_low_keys(trans, root, path, &node->ptrs[0].key, | 1271 | wret = fixup_low_keys(trans, root, path, &node->ptrs[0].key, |
1265 | level + 1); | 1272 | level + 1); |
1266 | if (wret) | 1273 | if (wret) |
1267 | ret = wret; | 1274 | ret = wret; |
1268 | } | 1275 | } |
1269 | BUG_ON(list_empty(&parent->dirty)); | 1276 | BUG_ON(!buffer_dirty(parent)); |
1270 | return ret; | 1277 | return ret; |
1271 | } | 1278 | } |
1272 | 1279 | ||
@@ -1279,7 +1286,7 @@ int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
1279 | { | 1286 | { |
1280 | int slot; | 1287 | int slot; |
1281 | struct btrfs_leaf *leaf; | 1288 | struct btrfs_leaf *leaf; |
1282 | struct btrfs_buffer *leaf_buf; | 1289 | struct buffer_head *leaf_buf; |
1283 | int doff; | 1290 | int doff; |
1284 | int dsize; | 1291 | int dsize; |
1285 | int ret = 0; | 1292 | int ret = 0; |
@@ -1287,7 +1294,7 @@ int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
1287 | u32 nritems; | 1294 | u32 nritems; |
1288 | 1295 | ||
1289 | leaf_buf = path->nodes[0]; | 1296 | leaf_buf = path->nodes[0]; |
1290 | leaf = &leaf_buf->leaf; | 1297 | leaf = btrfs_buffer_leaf(leaf_buf); |
1291 | slot = path->slots[0]; | 1298 | slot = path->slots[0]; |
1292 | doff = btrfs_item_offset(leaf->items + slot); | 1299 | doff = btrfs_item_offset(leaf->items + slot); |
1293 | dsize = btrfs_item_size(leaf->items + slot); | 1300 | dsize = btrfs_item_size(leaf->items + slot); |
@@ -1313,14 +1320,13 @@ int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
1313 | if (nritems == 0) { | 1320 | if (nritems == 0) { |
1314 | if (leaf_buf == root->node) { | 1321 | if (leaf_buf == root->node) { |
1315 | btrfs_set_header_level(&leaf->header, 0); | 1322 | btrfs_set_header_level(&leaf->header, 0); |
1316 | BUG_ON(list_empty(&leaf_buf->dirty)); | ||
1317 | } else { | 1323 | } else { |
1318 | clean_tree_block(trans, root, leaf_buf); | 1324 | clean_tree_block(trans, root, leaf_buf); |
1319 | wret = del_ptr(trans, root, path, 1, path->slots[1]); | 1325 | wret = del_ptr(trans, root, path, 1, path->slots[1]); |
1320 | if (wret) | 1326 | if (wret) |
1321 | ret = wret; | 1327 | ret = wret; |
1322 | wret = btrfs_free_extent(trans, root, | 1328 | wret = btrfs_free_extent(trans, root, |
1323 | leaf_buf->blocknr, 1, 1); | 1329 | leaf_buf->b_blocknr, 1, 1); |
1324 | if (wret) | 1330 | if (wret) |
1325 | ret = wret; | 1331 | ret = wret; |
1326 | } | 1332 | } |
@@ -1332,7 +1338,6 @@ int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
1332 | if (wret) | 1338 | if (wret) |
1333 | ret = wret; | 1339 | ret = wret; |
1334 | } | 1340 | } |
1335 | BUG_ON(list_empty(&leaf_buf->dirty)); | ||
1336 | 1341 | ||
1337 | /* delete the leaf if it is mostly empty */ | 1342 | /* delete the leaf if it is mostly empty */ |
1338 | if (used < BTRFS_LEAF_DATA_SIZE(root) / 3) { | 1343 | if (used < BTRFS_LEAF_DATA_SIZE(root) / 3) { |
@@ -1341,7 +1346,7 @@ int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
1341 | * for possible call to del_ptr below | 1346 | * for possible call to del_ptr below |
1342 | */ | 1347 | */ |
1343 | slot = path->slots[1]; | 1348 | slot = path->slots[1]; |
1344 | leaf_buf->count++; | 1349 | get_bh(leaf_buf); |
1345 | wret = push_leaf_left(trans, root, path, 1); | 1350 | wret = push_leaf_left(trans, root, path, 1); |
1346 | if (wret < 0) | 1351 | if (wret < 0) |
1347 | ret = wret; | 1352 | ret = wret; |
@@ -1352,7 +1357,7 @@ int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
1352 | ret = wret; | 1357 | ret = wret; |
1353 | } | 1358 | } |
1354 | if (btrfs_header_nritems(&leaf->header) == 0) { | 1359 | if (btrfs_header_nritems(&leaf->header) == 0) { |
1355 | u64 blocknr = leaf_buf->blocknr; | 1360 | u64 blocknr = leaf_buf->b_blocknr; |
1356 | clean_tree_block(trans, root, leaf_buf); | 1361 | clean_tree_block(trans, root, leaf_buf); |
1357 | wret = del_ptr(trans, root, path, 1, slot); | 1362 | wret = del_ptr(trans, root, path, 1, slot); |
1358 | if (wret) | 1363 | if (wret) |
@@ -1380,19 +1385,21 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path) | |||
1380 | int slot; | 1385 | int slot; |
1381 | int level = 1; | 1386 | int level = 1; |
1382 | u64 blocknr; | 1387 | u64 blocknr; |
1383 | struct btrfs_buffer *c; | 1388 | struct buffer_head *c; |
1384 | struct btrfs_buffer *next = NULL; | 1389 | struct btrfs_node *c_node; |
1390 | struct buffer_head *next = NULL; | ||
1385 | 1391 | ||
1386 | while(level < BTRFS_MAX_LEVEL) { | 1392 | while(level < BTRFS_MAX_LEVEL) { |
1387 | if (!path->nodes[level]) | 1393 | if (!path->nodes[level]) |
1388 | return 1; | 1394 | return 1; |
1389 | slot = path->slots[level] + 1; | 1395 | slot = path->slots[level] + 1; |
1390 | c = path->nodes[level]; | 1396 | c = path->nodes[level]; |
1391 | if (slot >= btrfs_header_nritems(&c->node.header)) { | 1397 | c_node = btrfs_buffer_node(c); |
1398 | if (slot >= btrfs_header_nritems(&c_node->header)) { | ||
1392 | level++; | 1399 | level++; |
1393 | continue; | 1400 | continue; |
1394 | } | 1401 | } |
1395 | blocknr = btrfs_node_blockptr(&c->node, slot); | 1402 | blocknr = btrfs_node_blockptr(c_node, slot); |
1396 | if (next) | 1403 | if (next) |
1397 | btrfs_block_release(root, next); | 1404 | btrfs_block_release(root, next); |
1398 | next = read_tree_block(root, blocknr); | 1405 | next = read_tree_block(root, blocknr); |
@@ -1408,7 +1415,7 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path) | |||
1408 | if (!level) | 1415 | if (!level) |
1409 | break; | 1416 | break; |
1410 | next = read_tree_block(root, | 1417 | next = read_tree_block(root, |
1411 | btrfs_node_blockptr(&next->node, 0)); | 1418 | btrfs_node_blockptr(btrfs_buffer_node(next), 0)); |
1412 | } | 1419 | } |
1413 | return 0; | 1420 | return 0; |
1414 | } | 1421 | } |
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index ae8518cb94bf..7748eecd9304 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -1,6 +1,9 @@ | |||
1 | #ifndef __BTRFS__ | 1 | #ifndef __BTRFS__ |
2 | #define __BTRFS__ | 2 | #define __BTRFS__ |
3 | 3 | ||
4 | #include <linux/radix-tree.h> | ||
5 | #include <linux/fs.h> | ||
6 | |||
4 | struct btrfs_trans_handle; | 7 | struct btrfs_trans_handle; |
5 | 8 | ||
6 | #define BTRFS_MAGIC "_BtRfS_M" | 9 | #define BTRFS_MAGIC "_BtRfS_M" |
@@ -11,6 +14,12 @@ struct btrfs_trans_handle; | |||
11 | #define BTRFS_FS_TREE_OBJECTID 4 | 14 | #define BTRFS_FS_TREE_OBJECTID 4 |
12 | 15 | ||
13 | /* | 16 | /* |
17 | * we can actually store much bigger names, but lets not confuse the rest | ||
18 | * of linux | ||
19 | */ | ||
20 | #define BTRFS_NAME_LEN 255 | ||
21 | |||
22 | /* | ||
14 | * the key defines the order in the tree, and so it also defines (optimal) | 23 | * the key defines the order in the tree, and so it also defines (optimal) |
15 | * block layout. objectid corresonds to the inode number. The flags | 24 | * block layout. objectid corresonds to the inode number. The flags |
16 | * tells us things about the object, and is a kind of stream selector. | 25 | * tells us things about the object, and is a kind of stream selector. |
@@ -57,7 +66,7 @@ struct btrfs_header { | |||
57 | #define __BTRFS_LEAF_DATA_SIZE(bs) ((bs) - sizeof(struct btrfs_header)) | 66 | #define __BTRFS_LEAF_DATA_SIZE(bs) ((bs) - sizeof(struct btrfs_header)) |
58 | #define BTRFS_LEAF_DATA_SIZE(r) (__BTRFS_LEAF_DATA_SIZE(r->blocksize)) | 67 | #define BTRFS_LEAF_DATA_SIZE(r) (__BTRFS_LEAF_DATA_SIZE(r->blocksize)) |
59 | 68 | ||
60 | struct btrfs_buffer; | 69 | struct buffer_head; |
61 | /* | 70 | /* |
62 | * the super block basically lists the main trees of the FS | 71 | * the super block basically lists the main trees of the FS |
63 | * it currently lacks any block count etc etc | 72 | * it currently lacks any block count etc etc |
@@ -120,7 +129,7 @@ struct btrfs_node { | |||
120 | * used while walking the tree. | 129 | * used while walking the tree. |
121 | */ | 130 | */ |
122 | struct btrfs_path { | 131 | struct btrfs_path { |
123 | struct btrfs_buffer *nodes[BTRFS_MAX_LEVEL]; | 132 | struct buffer_head *nodes[BTRFS_MAX_LEVEL]; |
124 | int slots[BTRFS_MAX_LEVEL]; | 133 | int slots[BTRFS_MAX_LEVEL]; |
125 | }; | 134 | }; |
126 | 135 | ||
@@ -211,17 +220,14 @@ struct btrfs_fs_info { | |||
211 | struct btrfs_root *inode_root; | 220 | struct btrfs_root *inode_root; |
212 | struct btrfs_key current_insert; | 221 | struct btrfs_key current_insert; |
213 | struct btrfs_key last_insert; | 222 | struct btrfs_key last_insert; |
214 | struct radix_tree_root cache_radix; | ||
215 | struct radix_tree_root pinned_radix; | 223 | struct radix_tree_root pinned_radix; |
216 | struct list_head trans; | ||
217 | struct list_head cache; | ||
218 | u64 last_inode_alloc; | 224 | u64 last_inode_alloc; |
219 | u64 last_inode_alloc_dirid; | 225 | u64 last_inode_alloc_dirid; |
220 | u64 generation; | 226 | u64 generation; |
221 | int cache_size; | ||
222 | int fp; | ||
223 | struct btrfs_trans_handle *running_transaction; | 227 | struct btrfs_trans_handle *running_transaction; |
224 | struct btrfs_super_block *disk_super; | 228 | struct btrfs_super_block *disk_super; |
229 | struct buffer_head *sb_buffer; | ||
230 | struct super_block *sb; | ||
225 | }; | 231 | }; |
226 | 232 | ||
227 | /* | 233 | /* |
@@ -230,8 +236,8 @@ struct btrfs_fs_info { | |||
230 | * only for the extent tree. | 236 | * only for the extent tree. |
231 | */ | 237 | */ |
232 | struct btrfs_root { | 238 | struct btrfs_root { |
233 | struct btrfs_buffer *node; | 239 | struct buffer_head *node; |
234 | struct btrfs_buffer *commit_root; | 240 | struct buffer_head *commit_root; |
235 | struct btrfs_root_item root_item; | 241 | struct btrfs_root_item root_item; |
236 | struct btrfs_key root_key; | 242 | struct btrfs_key root_key; |
237 | struct btrfs_fs_info *fs_info; | 243 | struct btrfs_fs_info *fs_info; |
@@ -389,6 +395,29 @@ static inline void btrfs_set_inode_compat_flags(struct btrfs_inode_item *i, | |||
389 | i->compat_flags = cpu_to_le16(val); | 395 | i->compat_flags = cpu_to_le16(val); |
390 | } | 396 | } |
391 | 397 | ||
398 | static inline u32 btrfs_timespec_sec(struct btrfs_inode_timespec *ts) | ||
399 | { | ||
400 | return le32_to_cpu(ts->sec); | ||
401 | } | ||
402 | |||
403 | static inline void btrfs_set_timespec_sec(struct btrfs_inode_timespec *ts, | ||
404 | u32 val) | ||
405 | { | ||
406 | ts->sec = cpu_to_le32(val); | ||
407 | } | ||
408 | |||
409 | static inline u32 btrfs_timespec_nsec(struct btrfs_inode_timespec *ts) | ||
410 | { | ||
411 | return le32_to_cpu(ts->nsec); | ||
412 | } | ||
413 | |||
414 | static inline void btrfs_set_timespec_nsec(struct btrfs_inode_timespec *ts, | ||
415 | u32 val) | ||
416 | { | ||
417 | ts->nsec = cpu_to_le32(val); | ||
418 | } | ||
419 | |||
420 | |||
392 | 421 | ||
393 | static inline u64 btrfs_extent_owner(struct btrfs_extent_item *ei) | 422 | static inline u64 btrfs_extent_owner(struct btrfs_extent_item *ei) |
394 | { | 423 | { |
@@ -757,15 +786,20 @@ static inline void btrfs_set_file_extent_num_blocks(struct | |||
757 | e->num_blocks = cpu_to_le64(val); | 786 | e->num_blocks = cpu_to_le64(val); |
758 | } | 787 | } |
759 | 788 | ||
789 | static inline struct btrfs_root *btrfs_sb(struct super_block *sb) | ||
790 | { | ||
791 | return sb->s_fs_info; | ||
792 | } | ||
793 | |||
760 | /* helper function to cast into the data area of the leaf. */ | 794 | /* helper function to cast into the data area of the leaf. */ |
761 | #define btrfs_item_ptr(leaf, slot, type) \ | 795 | #define btrfs_item_ptr(leaf, slot, type) \ |
762 | ((type *)(btrfs_leaf_data(leaf) + \ | 796 | ((type *)(btrfs_leaf_data(leaf) + \ |
763 | btrfs_item_offset((leaf)->items + (slot)))) | 797 | btrfs_item_offset((leaf)->items + (slot)))) |
764 | 798 | ||
765 | struct btrfs_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans, | 799 | struct buffer_head *btrfs_alloc_free_block(struct btrfs_trans_handle *trans, |
766 | struct btrfs_root *root); | 800 | struct btrfs_root *root); |
767 | int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 801 | int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
768 | struct btrfs_buffer *buf); | 802 | struct buffer_head *buf); |
769 | int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | 803 | int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root |
770 | *root, u64 blocknr, u64 num_blocks, int pin); | 804 | *root, u64 blocknr, u64 num_blocks, int pin); |
771 | int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root | 805 | int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root |
@@ -783,7 +817,7 @@ int btrfs_insert_empty_item(struct btrfs_trans_handle *trans, struct btrfs_root | |||
783 | int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path); | 817 | int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path); |
784 | int btrfs_leaf_free_space(struct btrfs_root *root, struct btrfs_leaf *leaf); | 818 | int btrfs_leaf_free_space(struct btrfs_root *root, struct btrfs_leaf *leaf); |
785 | int btrfs_drop_snapshot(struct btrfs_trans_handle *trans, struct btrfs_root | 819 | int btrfs_drop_snapshot(struct btrfs_trans_handle *trans, struct btrfs_root |
786 | *root, struct btrfs_buffer *snap); | 820 | *root, struct buffer_head *snap); |
787 | int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct | 821 | int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct |
788 | btrfs_root *root); | 822 | btrfs_root *root); |
789 | int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 823 | int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
@@ -800,8 +834,8 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root | |||
800 | *root, char *name, int name_len, u64 dir, u64 | 834 | *root, char *name, int name_len, u64 dir, u64 |
801 | objectid, u8 type); | 835 | objectid, u8 type); |
802 | int btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root | 836 | int btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root |
803 | *root, struct btrfs_path *path, u64 dir, char *name, | 837 | *root, struct btrfs_path *path, u64 dir, |
804 | int name_len, int mod); | 838 | const char *name, int name_len, int mod); |
805 | int btrfs_match_dir_item_name(struct btrfs_root *root, struct btrfs_path *path, | 839 | int btrfs_match_dir_item_name(struct btrfs_root *root, struct btrfs_path *path, |
806 | char *name, int name_len); | 840 | char *name, int name_len); |
807 | int btrfs_find_free_objectid(struct btrfs_trans_handle *trans, | 841 | int btrfs_find_free_objectid(struct btrfs_trans_handle *trans, |
diff --git a/fs/btrfs/dir-item.c b/fs/btrfs/dir-item.c index 4d8083d92fa0..75d6e373e98d 100644 --- a/fs/btrfs/dir-item.c +++ b/fs/btrfs/dir-item.c | |||
@@ -18,12 +18,7 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root | |||
18 | key.objectid = dir; | 18 | key.objectid = dir; |
19 | key.flags = 0; | 19 | key.flags = 0; |
20 | btrfs_set_key_type(&key, BTRFS_DIR_ITEM_KEY); | 20 | btrfs_set_key_type(&key, BTRFS_DIR_ITEM_KEY); |
21 | if (name_len == 1 && *name == '.') | 21 | ret = btrfs_name_hash(name, name_len, &key.offset); |
22 | key.offset = 1; | ||
23 | else if (name_len == 2 && name[0] == '.' && name[1] == '.') | ||
24 | key.offset = 2; | ||
25 | else | ||
26 | ret = btrfs_name_hash(name, name_len, &key.offset); | ||
27 | BUG_ON(ret); | 22 | BUG_ON(ret); |
28 | btrfs_init_path(&path); | 23 | btrfs_init_path(&path); |
29 | data_size = sizeof(*dir_item) + name_len; | 24 | data_size = sizeof(*dir_item) + name_len; |
@@ -31,7 +26,8 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root | |||
31 | if (ret) | 26 | if (ret) |
32 | goto out; | 27 | goto out; |
33 | 28 | ||
34 | dir_item = btrfs_item_ptr(&path.nodes[0]->leaf, path.slots[0], | 29 | dir_item = btrfs_item_ptr(btrfs_buffer_leaf(path.nodes[0]), |
30 | path.slots[0], | ||
35 | struct btrfs_dir_item); | 31 | struct btrfs_dir_item); |
36 | btrfs_set_dir_objectid(dir_item, objectid); | 32 | btrfs_set_dir_objectid(dir_item, objectid); |
37 | btrfs_set_dir_type(dir_item, type); | 33 | btrfs_set_dir_type(dir_item, type); |
@@ -45,8 +41,8 @@ out: | |||
45 | } | 41 | } |
46 | 42 | ||
47 | int btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root | 43 | int btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root |
48 | *root, struct btrfs_path *path, u64 dir, char *name, | 44 | *root, struct btrfs_path *path, u64 dir, |
49 | int name_len, int mod) | 45 | const char *name, int name_len, int mod) |
50 | { | 46 | { |
51 | int ret; | 47 | int ret; |
52 | struct btrfs_key key; | 48 | struct btrfs_key key; |
@@ -69,7 +65,8 @@ int btrfs_match_dir_item_name(struct btrfs_root *root, | |||
69 | struct btrfs_dir_item *dir_item; | 65 | struct btrfs_dir_item *dir_item; |
70 | char *name_ptr; | 66 | char *name_ptr; |
71 | 67 | ||
72 | dir_item = btrfs_item_ptr(&path->nodes[0]->leaf, path->slots[0], | 68 | dir_item = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), |
69 | path->slots[0], | ||
73 | struct btrfs_dir_item); | 70 | struct btrfs_dir_item); |
74 | if (btrfs_dir_name_len(dir_item) != name_len) | 71 | if (btrfs_dir_name_len(dir_item) != name_len) |
75 | return 0; | 72 | return 0; |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 05637f9fd7c7..df2061a735cd 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -1,165 +1,67 @@ | |||
1 | #define _XOPEN_SOURCE 500 | 1 | #include <linux/module.h> |
2 | #include <stdio.h> | 2 | #include <linux/fs.h> |
3 | #include <stdlib.h> | ||
4 | #include <sys/types.h> | ||
5 | #include <sys/stat.h> | ||
6 | #include <fcntl.h> | ||
7 | #include <unistd.h> | ||
8 | #include "kerncompat.h" | ||
9 | #include "radix-tree.h" | ||
10 | #include "ctree.h" | 3 | #include "ctree.h" |
11 | #include "disk-io.h" | 4 | #include "disk-io.h" |
12 | #include "transaction.h" | 5 | #include "transaction.h" |
13 | 6 | ||
14 | static int allocated_blocks = 0; | 7 | static int check_tree_block(struct btrfs_root *root, struct buffer_head *buf) |
15 | int cache_max = 10000; | ||
16 | |||
17 | static int check_tree_block(struct btrfs_root *root, struct btrfs_buffer *buf) | ||
18 | { | 8 | { |
19 | if (buf->blocknr != btrfs_header_blocknr(&buf->node.header)) | 9 | struct btrfs_node *node = btrfs_buffer_node(buf); |
10 | if (buf->b_blocknr != btrfs_header_blocknr(&node->header)) | ||
20 | BUG(); | 11 | BUG(); |
21 | if (root->node && btrfs_header_parentid(&buf->node.header) != | 12 | if (root->node && btrfs_header_parentid(&node->header) != |
22 | btrfs_header_parentid(&root->node->node.header)) | 13 | btrfs_header_parentid(btrfs_buffer_header(root->node))) |
23 | BUG(); | 14 | BUG(); |
24 | return 0; | 15 | return 0; |
25 | } | 16 | } |
26 | 17 | ||
27 | static int free_some_buffers(struct btrfs_root *root) | 18 | struct buffer_head *alloc_tree_block(struct btrfs_root *root, u64 blocknr) |
28 | { | 19 | { |
29 | struct list_head *node, *next; | 20 | return sb_getblk(root->fs_info->sb, blocknr); |
30 | struct btrfs_buffer *b; | ||
31 | if (root->fs_info->cache_size < cache_max) | ||
32 | return 0; | ||
33 | list_for_each_safe(node, next, &root->fs_info->cache) { | ||
34 | b = list_entry(node, struct btrfs_buffer, cache); | ||
35 | if (b->count == 1) { | ||
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) | ||
40 | break; | ||
41 | } | ||
42 | } | ||
43 | return 0; | ||
44 | } | 21 | } |
45 | 22 | ||
46 | struct btrfs_buffer *alloc_tree_block(struct btrfs_root *root, u64 blocknr) | 23 | struct buffer_head *find_tree_block(struct btrfs_root *root, u64 blocknr) |
47 | { | 24 | { |
48 | struct btrfs_buffer *buf; | 25 | return sb_getblk(root->fs_info->sb, blocknr); |
49 | int ret; | ||
50 | |||
51 | buf = malloc(sizeof(struct btrfs_buffer) + root->blocksize); | ||
52 | if (!buf) | ||
53 | return buf; | ||
54 | allocated_blocks++; | ||
55 | buf->blocknr = blocknr; | ||
56 | buf->count = 2; | ||
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++; | ||
64 | if (ret) { | ||
65 | free(buf); | ||
66 | return NULL; | ||
67 | } | ||
68 | return buf; | ||
69 | } | 26 | } |
70 | 27 | ||
71 | struct btrfs_buffer *find_tree_block(struct btrfs_root *root, u64 blocknr) | 28 | struct buffer_head *read_tree_block(struct btrfs_root *root, u64 blocknr) |
72 | { | 29 | { |
73 | struct btrfs_buffer *buf; | 30 | struct buffer_head *buf = sb_bread(root->fs_info->sb, blocknr); |
74 | buf = radix_tree_lookup(&root->fs_info->cache_radix, blocknr); | ||
75 | if (buf) { | ||
76 | buf->count++; | ||
77 | } else { | ||
78 | buf = alloc_tree_block(root, blocknr); | ||
79 | if (!buf) { | ||
80 | BUG(); | ||
81 | return NULL; | ||
82 | } | ||
83 | } | ||
84 | return buf; | ||
85 | } | ||
86 | |||
87 | struct btrfs_buffer *read_tree_block(struct btrfs_root *root, u64 blocknr) | ||
88 | { | ||
89 | loff_t offset = blocknr * root->blocksize; | ||
90 | struct btrfs_buffer *buf; | ||
91 | int ret; | ||
92 | 31 | ||
93 | buf = radix_tree_lookup(&root->fs_info->cache_radix, blocknr); | 32 | if (!buf) |
94 | if (buf) { | 33 | return buf; |
95 | buf->count++; | ||
96 | } else { | ||
97 | buf = alloc_tree_block(root, blocknr); | ||
98 | if (!buf) | ||
99 | return NULL; | ||
100 | ret = pread(root->fs_info->fp, &buf->node, root->blocksize, | ||
101 | offset); | ||
102 | if (ret != root->blocksize) { | ||
103 | free(buf); | ||
104 | return NULL; | ||
105 | } | ||
106 | } | ||
107 | if (check_tree_block(root, buf)) | 34 | if (check_tree_block(root, buf)) |
108 | BUG(); | 35 | BUG(); |
109 | return buf; | 36 | return buf; |
110 | } | 37 | } |
111 | 38 | ||
112 | int dirty_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 39 | int dirty_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
113 | struct btrfs_buffer *buf) | 40 | struct buffer_head *buf) |
114 | { | 41 | { |
115 | if (!list_empty(&buf->dirty)) | 42 | mark_buffer_dirty(buf); |
116 | return 0; | ||
117 | list_add_tail(&buf->dirty, &root->fs_info->trans); | ||
118 | buf->count++; | ||
119 | return 0; | 43 | return 0; |
120 | } | 44 | } |
121 | 45 | ||
122 | int clean_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 46 | int clean_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
123 | struct btrfs_buffer *buf) | 47 | struct buffer_head *buf) |
124 | { | 48 | { |
125 | if (!list_empty(&buf->dirty)) { | 49 | clear_buffer_dirty(buf); |
126 | list_del_init(&buf->dirty); | ||
127 | btrfs_block_release(root, buf); | ||
128 | } | ||
129 | return 0; | 50 | return 0; |
130 | } | 51 | } |
131 | 52 | ||
132 | int write_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 53 | int write_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
133 | struct btrfs_buffer *buf) | 54 | struct buffer_head *buf) |
134 | { | 55 | { |
135 | u64 blocknr = buf->blocknr; | 56 | mark_buffer_dirty(buf); |
136 | loff_t offset = blocknr * root->blocksize; | ||
137 | int ret; | ||
138 | |||
139 | if (buf->blocknr != btrfs_header_blocknr(&buf->node.header)) | ||
140 | BUG(); | ||
141 | ret = pwrite(root->fs_info->fp, &buf->node, root->blocksize, offset); | ||
142 | if (ret != root->blocksize) | ||
143 | return ret; | ||
144 | return 0; | 57 | return 0; |
145 | } | 58 | } |
146 | 59 | ||
147 | static int __commit_transaction(struct btrfs_trans_handle *trans, struct | 60 | static int __commit_transaction(struct btrfs_trans_handle *trans, struct |
148 | btrfs_root *root) | 61 | btrfs_root *root) |
149 | { | 62 | { |
150 | struct btrfs_buffer *b; | 63 | filemap_write_and_wait(root->fs_info->sb->s_bdev->bd_inode->i_mapping); |
151 | int ret = 0; | 64 | return 0; |
152 | int wret; | ||
153 | while(!list_empty(&root->fs_info->trans)) { | ||
154 | b = list_entry(root->fs_info->trans.next, struct btrfs_buffer, | ||
155 | dirty); | ||
156 | list_del_init(&b->dirty); | ||
157 | wret = write_tree_block(trans, root, b); | ||
158 | if (wret) | ||
159 | ret = wret; | ||
160 | btrfs_block_release(root, b); | ||
161 | } | ||
162 | return ret; | ||
163 | } | 65 | } |
164 | 66 | ||
165 | static int commit_tree_roots(struct btrfs_trans_handle *trans, | 67 | static int commit_tree_roots(struct btrfs_trans_handle *trans, |
@@ -172,17 +74,17 @@ static int commit_tree_roots(struct btrfs_trans_handle *trans, | |||
172 | struct btrfs_root *inode_root = fs_info->inode_root; | 74 | struct btrfs_root *inode_root = fs_info->inode_root; |
173 | 75 | ||
174 | btrfs_set_root_blocknr(&inode_root->root_item, | 76 | btrfs_set_root_blocknr(&inode_root->root_item, |
175 | inode_root->node->blocknr); | 77 | inode_root->node->b_blocknr); |
176 | ret = btrfs_update_root(trans, tree_root, | 78 | ret = btrfs_update_root(trans, tree_root, |
177 | &inode_root->root_key, | 79 | &inode_root->root_key, |
178 | &inode_root->root_item); | 80 | &inode_root->root_item); |
179 | BUG_ON(ret); | 81 | BUG_ON(ret); |
180 | while(1) { | 82 | while(1) { |
181 | old_extent_block = btrfs_root_blocknr(&extent_root->root_item); | 83 | old_extent_block = btrfs_root_blocknr(&extent_root->root_item); |
182 | if (old_extent_block == extent_root->node->blocknr) | 84 | if (old_extent_block == extent_root->node->b_blocknr) |
183 | break; | 85 | break; |
184 | btrfs_set_root_blocknr(&extent_root->root_item, | 86 | btrfs_set_root_blocknr(&extent_root->root_item, |
185 | extent_root->node->blocknr); | 87 | extent_root->node->b_blocknr); |
186 | ret = btrfs_update_root(trans, tree_root, | 88 | ret = btrfs_update_root(trans, tree_root, |
187 | &extent_root->root_key, | 89 | &extent_root->root_key, |
188 | &extent_root->root_item); | 90 | &extent_root->root_item); |
@@ -195,7 +97,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, struct | |||
195 | btrfs_root *root, struct btrfs_super_block *s) | 97 | btrfs_root *root, struct btrfs_super_block *s) |
196 | { | 98 | { |
197 | int ret = 0; | 99 | int ret = 0; |
198 | struct btrfs_buffer *snap = root->commit_root; | 100 | struct buffer_head *snap = root->commit_root; |
199 | struct btrfs_key snap_key; | 101 | struct btrfs_key snap_key; |
200 | 102 | ||
201 | if (root->commit_root == root->node) | 103 | if (root->commit_root == root->node) |
@@ -204,7 +106,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, struct | |||
204 | memcpy(&snap_key, &root->root_key, sizeof(snap_key)); | 106 | memcpy(&snap_key, &root->root_key, sizeof(snap_key)); |
205 | root->root_key.offset++; | 107 | root->root_key.offset++; |
206 | 108 | ||
207 | btrfs_set_root_blocknr(&root->root_item, root->node->blocknr); | 109 | btrfs_set_root_blocknr(&root->root_item, root->node->b_blocknr); |
208 | ret = btrfs_insert_root(trans, root->fs_info->tree_root, | 110 | ret = btrfs_insert_root(trans, root->fs_info->tree_root, |
209 | &root->root_key, &root->root_item); | 111 | &root->root_key, &root->root_item); |
210 | BUG_ON(ret); | 112 | BUG_ON(ret); |
@@ -220,7 +122,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, struct | |||
220 | btrfs_finish_extent_commit(trans, root->fs_info->tree_root); | 122 | btrfs_finish_extent_commit(trans, root->fs_info->tree_root); |
221 | 123 | ||
222 | root->commit_root = root->node; | 124 | root->commit_root = root->node; |
223 | root->node->count++; | 125 | get_bh(root->node); |
224 | ret = btrfs_drop_snapshot(trans, root, snap); | 126 | ret = btrfs_drop_snapshot(trans, root, snap); |
225 | BUG_ON(ret); | 127 | BUG_ON(ret); |
226 | 128 | ||
@@ -234,7 +136,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, struct | |||
234 | static int __setup_root(struct btrfs_super_block *super, | 136 | static int __setup_root(struct btrfs_super_block *super, |
235 | struct btrfs_root *root, | 137 | struct btrfs_root *root, |
236 | struct btrfs_fs_info *fs_info, | 138 | struct btrfs_fs_info *fs_info, |
237 | u64 objectid, int fp) | 139 | u64 objectid) |
238 | { | 140 | { |
239 | root->node = NULL; | 141 | root->node = NULL; |
240 | root->commit_root = NULL; | 142 | root->commit_root = NULL; |
@@ -250,11 +152,11 @@ static int find_and_setup_root(struct btrfs_super_block *super, | |||
250 | struct btrfs_root *tree_root, | 152 | struct btrfs_root *tree_root, |
251 | struct btrfs_fs_info *fs_info, | 153 | struct btrfs_fs_info *fs_info, |
252 | u64 objectid, | 154 | u64 objectid, |
253 | struct btrfs_root *root, int fp) | 155 | struct btrfs_root *root) |
254 | { | 156 | { |
255 | int ret; | 157 | int ret; |
256 | 158 | ||
257 | __setup_root(super, root, fs_info, objectid, fp); | 159 | __setup_root(super, root, fs_info, objectid); |
258 | ret = btrfs_find_last_root(tree_root, objectid, | 160 | ret = btrfs_find_last_root(tree_root, objectid, |
259 | &root->root_item, &root->root_key); | 161 | &root->root_item, &root->root_key); |
260 | BUG_ON(ret); | 162 | BUG_ON(ret); |
@@ -265,32 +167,26 @@ static int find_and_setup_root(struct btrfs_super_block *super, | |||
265 | return 0; | 167 | return 0; |
266 | } | 168 | } |
267 | 169 | ||
268 | struct btrfs_root *open_ctree(char *filename, struct btrfs_super_block *super) | 170 | struct btrfs_root *open_ctree(struct super_block *sb, |
171 | struct buffer_head *sb_buffer, | ||
172 | struct btrfs_super_block *disk_super) | ||
269 | { | 173 | { |
270 | int fp; | 174 | struct btrfs_root *root = kmalloc(sizeof(struct btrfs_root), |
271 | 175 | GFP_NOFS); | |
272 | fp = open(filename, O_CREAT | O_RDWR, 0600); | 176 | struct btrfs_root *extent_root = kmalloc(sizeof(struct btrfs_root), |
273 | if (fp < 0) { | 177 | GFP_NOFS); |
274 | return NULL; | 178 | struct btrfs_root *tree_root = kmalloc(sizeof(struct btrfs_root), |
275 | } | 179 | GFP_NOFS); |
276 | return open_ctree_fd(fp, super); | 180 | struct btrfs_root *inode_root = kmalloc(sizeof(struct btrfs_root), |
277 | } | 181 | GFP_NOFS); |
278 | 182 | struct btrfs_fs_info *fs_info = kmalloc(sizeof(*fs_info), | |
279 | struct btrfs_root *open_ctree_fd(int fp, struct btrfs_super_block *super) | 183 | GFP_NOFS); |
280 | { | ||
281 | struct btrfs_root *root = malloc(sizeof(struct btrfs_root)); | ||
282 | struct btrfs_root *extent_root = malloc(sizeof(struct btrfs_root)); | ||
283 | struct btrfs_root *tree_root = malloc(sizeof(struct btrfs_root)); | ||
284 | struct btrfs_root *inode_root = malloc(sizeof(struct btrfs_root)); | ||
285 | struct btrfs_fs_info *fs_info = malloc(sizeof(*fs_info)); | ||
286 | int ret; | 184 | int ret; |
287 | 185 | ||
288 | INIT_RADIX_TREE(&fs_info->cache_radix, GFP_KERNEL); | 186 | /* FIXME: don't be stupid */ |
187 | if (!btrfs_super_root(disk_super)) | ||
188 | return NULL; | ||
289 | INIT_RADIX_TREE(&fs_info->pinned_radix, GFP_KERNEL); | 189 | INIT_RADIX_TREE(&fs_info->pinned_radix, GFP_KERNEL); |
290 | INIT_LIST_HEAD(&fs_info->trans); | ||
291 | INIT_LIST_HEAD(&fs_info->cache); | ||
292 | fs_info->cache_size = 0; | ||
293 | fs_info->fp = fp; | ||
294 | fs_info->running_transaction = NULL; | 190 | fs_info->running_transaction = NULL; |
295 | fs_info->fs_root = root; | 191 | fs_info->fs_root = root; |
296 | fs_info->tree_root = tree_root; | 192 | fs_info->tree_root = tree_root; |
@@ -298,36 +194,31 @@ struct btrfs_root *open_ctree_fd(int fp, struct btrfs_super_block *super) | |||
298 | fs_info->inode_root = inode_root; | 194 | fs_info->inode_root = inode_root; |
299 | fs_info->last_inode_alloc = 0; | 195 | fs_info->last_inode_alloc = 0; |
300 | fs_info->last_inode_alloc_dirid = 0; | 196 | fs_info->last_inode_alloc_dirid = 0; |
301 | fs_info->disk_super = super; | 197 | fs_info->disk_super = disk_super; |
198 | fs_info->sb_buffer = sb_buffer; | ||
199 | fs_info->sb = sb; | ||
302 | memset(&fs_info->current_insert, 0, sizeof(fs_info->current_insert)); | 200 | memset(&fs_info->current_insert, 0, sizeof(fs_info->current_insert)); |
303 | memset(&fs_info->last_insert, 0, sizeof(fs_info->last_insert)); | 201 | memset(&fs_info->last_insert, 0, sizeof(fs_info->last_insert)); |
304 | 202 | ||
305 | ret = pread(fp, super, sizeof(struct btrfs_super_block), | 203 | __setup_root(disk_super, tree_root, fs_info, BTRFS_ROOT_TREE_OBJECTID); |
306 | BTRFS_SUPER_INFO_OFFSET); | 204 | tree_root->node = read_tree_block(tree_root, |
307 | if (ret == 0 || btrfs_super_root(super) == 0) { | 205 | btrfs_super_root(disk_super)); |
308 | BUG(); | ||
309 | return NULL; | ||
310 | } | ||
311 | BUG_ON(ret < 0); | ||
312 | |||
313 | __setup_root(super, tree_root, fs_info, BTRFS_ROOT_TREE_OBJECTID, fp); | ||
314 | tree_root->node = read_tree_block(tree_root, btrfs_super_root(super)); | ||
315 | BUG_ON(!tree_root->node); | 206 | BUG_ON(!tree_root->node); |
316 | 207 | ||
317 | ret = find_and_setup_root(super, tree_root, fs_info, | 208 | ret = find_and_setup_root(disk_super, tree_root, fs_info, |
318 | BTRFS_EXTENT_TREE_OBJECTID, extent_root, fp); | 209 | BTRFS_EXTENT_TREE_OBJECTID, extent_root); |
319 | BUG_ON(ret); | 210 | BUG_ON(ret); |
320 | 211 | ||
321 | ret = find_and_setup_root(super, tree_root, fs_info, | 212 | ret = find_and_setup_root(disk_super, tree_root, fs_info, |
322 | BTRFS_INODE_MAP_OBJECTID, inode_root, fp); | 213 | BTRFS_INODE_MAP_OBJECTID, inode_root); |
323 | BUG_ON(ret); | 214 | BUG_ON(ret); |
324 | 215 | ||
325 | ret = find_and_setup_root(super, tree_root, fs_info, | 216 | ret = find_and_setup_root(disk_super, tree_root, fs_info, |
326 | BTRFS_FS_TREE_OBJECTID, root, fp); | 217 | BTRFS_FS_TREE_OBJECTID, root); |
327 | BUG_ON(ret); | 218 | BUG_ON(ret); |
328 | 219 | ||
329 | root->commit_root = root->node; | 220 | root->commit_root = root->node; |
330 | root->node->count++; | 221 | get_bh(root->node); |
331 | root->ref_cows = 1; | 222 | root->ref_cows = 1; |
332 | root->fs_info->generation = root->root_key.offset + 1; | 223 | root->fs_info->generation = root->root_key.offset + 1; |
333 | return root; | 224 | return root; |
@@ -336,8 +227,11 @@ struct btrfs_root *open_ctree_fd(int fp, struct btrfs_super_block *super) | |||
336 | int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root | 227 | int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root |
337 | *root, struct btrfs_super_block *s) | 228 | *root, struct btrfs_super_block *s) |
338 | { | 229 | { |
230 | return 0; | ||
231 | #if 0 | ||
339 | int ret; | 232 | int ret; |
340 | btrfs_set_super_root(s, root->fs_info->tree_root->node->blocknr); | 233 | btrfs_set_super_root(s, root->fs_info->tree_root->node->b_blocknr); |
234 | |||
341 | ret = pwrite(root->fs_info->fp, s, sizeof(*s), | 235 | ret = pwrite(root->fs_info->fp, s, sizeof(*s), |
342 | BTRFS_SUPER_INFO_OFFSET); | 236 | BTRFS_SUPER_INFO_OFFSET); |
343 | if (ret != sizeof(*s)) { | 237 | if (ret != sizeof(*s)) { |
@@ -345,35 +239,38 @@ int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root | |||
345 | return ret; | 239 | return ret; |
346 | } | 240 | } |
347 | return 0; | 241 | return 0; |
242 | #endif | ||
348 | } | 243 | } |
349 | 244 | ||
350 | static int drop_cache(struct btrfs_root *root) | 245 | static int drop_cache(struct btrfs_root *root) |
351 | { | 246 | { |
247 | return 0; | ||
248 | #if 0 | ||
352 | while(!list_empty(&root->fs_info->cache)) { | 249 | while(!list_empty(&root->fs_info->cache)) { |
353 | struct btrfs_buffer *b = list_entry(root->fs_info->cache.next, | 250 | struct buffer_head *b = list_entry(root->fs_info->cache.next, |
354 | struct btrfs_buffer, | 251 | struct buffer_head, |
355 | cache); | 252 | cache); |
356 | list_del_init(&b->cache); | 253 | list_del_init(&b->cache); |
357 | btrfs_block_release(root, b); | 254 | btrfs_block_release(root, b); |
358 | } | 255 | } |
359 | return 0; | 256 | return 0; |
257 | #endif | ||
360 | } | 258 | } |
361 | int close_ctree(struct btrfs_root *root, struct btrfs_super_block *s) | 259 | |
260 | int close_ctree(struct btrfs_root *root) | ||
362 | { | 261 | { |
363 | int ret; | 262 | int ret; |
364 | struct btrfs_trans_handle *trans; | 263 | struct btrfs_trans_handle *trans; |
365 | 264 | ||
366 | trans = root->fs_info->running_transaction; | 265 | trans = root->fs_info->running_transaction; |
367 | btrfs_commit_transaction(trans, root, s); | 266 | btrfs_commit_transaction(trans, root, root->fs_info->disk_super); |
368 | ret = commit_tree_roots(trans, root->fs_info); | 267 | ret = commit_tree_roots(trans, root->fs_info); |
369 | BUG_ON(ret); | 268 | BUG_ON(ret); |
370 | ret = __commit_transaction(trans, root); | 269 | ret = __commit_transaction(trans, root); |
371 | BUG_ON(ret); | 270 | BUG_ON(ret); |
372 | write_ctree_super(trans, root, s); | 271 | write_ctree_super(trans, root, root->fs_info->disk_super); |
373 | drop_cache(root); | 272 | drop_cache(root); |
374 | BUG_ON(!list_empty(&root->fs_info->trans)); | ||
375 | 273 | ||
376 | close(root->fs_info->fp); | ||
377 | if (root->node) | 274 | if (root->node) |
378 | btrfs_block_release(root, root->node); | 275 | btrfs_block_release(root, root->node); |
379 | if (root->fs_info->extent_root->node) | 276 | if (root->fs_info->extent_root->node) |
@@ -386,29 +283,17 @@ int close_ctree(struct btrfs_root *root, struct btrfs_super_block *s) | |||
386 | btrfs_block_release(root->fs_info->tree_root, | 283 | btrfs_block_release(root->fs_info->tree_root, |
387 | root->fs_info->tree_root->node); | 284 | root->fs_info->tree_root->node); |
388 | btrfs_block_release(root, root->commit_root); | 285 | btrfs_block_release(root, root->commit_root); |
389 | free(root); | 286 | btrfs_block_release(root, root->fs_info->sb_buffer); |
390 | printf("on close %d blocks are allocated\n", allocated_blocks); | 287 | kfree(root->fs_info->extent_root); |
288 | kfree(root->fs_info->inode_root); | ||
289 | kfree(root->fs_info->tree_root); | ||
290 | kfree(root->fs_info); | ||
291 | kfree(root); | ||
391 | return 0; | 292 | return 0; |
392 | } | 293 | } |
393 | 294 | ||
394 | void btrfs_block_release(struct btrfs_root *root, struct btrfs_buffer *buf) | 295 | void btrfs_block_release(struct btrfs_root *root, struct buffer_head *buf) |
395 | { | 296 | { |
396 | buf->count--; | 297 | brelse(buf); |
397 | if (buf->count < 0) | ||
398 | BUG(); | ||
399 | if (buf->count == 0) { | ||
400 | BUG_ON(!list_empty(&buf->cache)); | ||
401 | BUG_ON(!list_empty(&buf->dirty)); | ||
402 | if (!radix_tree_lookup(&root->fs_info->cache_radix, | ||
403 | buf->blocknr)) | ||
404 | BUG(); | ||
405 | radix_tree_delete(&root->fs_info->cache_radix, buf->blocknr); | ||
406 | memset(buf, 0, sizeof(*buf)); | ||
407 | free(buf); | ||
408 | BUG_ON(allocated_blocks == 0); | ||
409 | allocated_blocks--; | ||
410 | BUG_ON(root->fs_info->cache_size == 0); | ||
411 | root->fs_info->cache_size--; | ||
412 | } | ||
413 | } | 298 | } |
414 | 299 | ||
diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h index d888cf5c350b..7f4bb729b734 100644 --- a/fs/btrfs/disk-io.h +++ b/fs/btrfs/disk-io.h | |||
@@ -1,36 +1,41 @@ | |||
1 | #ifndef __DISKIO__ | 1 | #ifndef __DISKIO__ |
2 | #define __DISKIO__ | 2 | #define __DISKIO__ |
3 | #include "list.h" | ||
4 | 3 | ||
5 | struct btrfs_buffer { | 4 | #include <linux/buffer_head.h> |
6 | u64 blocknr; | ||
7 | int count; | ||
8 | struct list_head dirty; | ||
9 | struct list_head cache; | ||
10 | union { | ||
11 | struct btrfs_node node; | ||
12 | struct btrfs_leaf leaf; | ||
13 | }; | ||
14 | }; | ||
15 | 5 | ||
16 | struct btrfs_buffer *read_tree_block(struct btrfs_root *root, u64 blocknr); | 6 | #define BTRFS_SUPER_INFO_OFFSET (16 * 1024) |
17 | struct btrfs_buffer *find_tree_block(struct btrfs_root *root, u64 blocknr); | 7 | |
8 | static inline struct btrfs_node *btrfs_buffer_node(struct buffer_head *bh) | ||
9 | { | ||
10 | return (struct btrfs_node *)bh->b_data; | ||
11 | } | ||
12 | |||
13 | static inline struct btrfs_leaf *btrfs_buffer_leaf(struct buffer_head *bh) | ||
14 | { | ||
15 | return (struct btrfs_leaf *)bh->b_data; | ||
16 | } | ||
17 | |||
18 | static inline struct btrfs_header *btrfs_buffer_header(struct buffer_head *bh) | ||
19 | { | ||
20 | return &((struct btrfs_node *)bh->b_data)->header; | ||
21 | } | ||
22 | |||
23 | struct buffer_head *read_tree_block(struct btrfs_root *root, u64 blocknr); | ||
24 | struct buffer_head *find_tree_block(struct btrfs_root *root, u64 blocknr); | ||
18 | int write_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 25 | int write_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
19 | struct btrfs_buffer *buf); | 26 | struct buffer_head *buf); |
20 | int dirty_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 27 | int dirty_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
21 | struct btrfs_buffer *buf); | 28 | struct buffer_head *buf); |
22 | int clean_tree_block(struct btrfs_trans_handle *trans, | 29 | int clean_tree_block(struct btrfs_trans_handle *trans, |
23 | struct btrfs_root *root, struct btrfs_buffer *buf); | 30 | struct btrfs_root *root, struct buffer_head *buf); |
24 | int btrfs_commit_transaction(struct btrfs_trans_handle *trans, struct btrfs_root | 31 | int btrfs_commit_transaction(struct btrfs_trans_handle *trans, struct btrfs_root |
25 | *root, struct btrfs_super_block *s); | 32 | *root, struct btrfs_super_block *s); |
26 | struct btrfs_root *open_ctree(char *filename, struct btrfs_super_block *s); | 33 | struct btrfs_root *open_ctree(struct super_block *sb, |
27 | struct btrfs_root *open_ctree_fd(int fp, struct btrfs_super_block *super); | 34 | struct buffer_head *sb_buffer, |
28 | int close_ctree(struct btrfs_root *root, struct btrfs_super_block *s); | 35 | struct btrfs_super_block *disk_super); |
29 | void btrfs_block_release(struct btrfs_root *root, struct btrfs_buffer *buf); | 36 | int close_ctree(struct btrfs_root *root); |
37 | void btrfs_block_release(struct btrfs_root *root, struct buffer_head *buf); | ||
30 | int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 38 | int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
31 | struct btrfs_super_block *s); | 39 | struct btrfs_super_block *s); |
32 | int mkfs(int fd, u64 num_blocks, u32 blocksize); | 40 | int mkfs(int fd, u64 num_blocks, u32 blocksize); |
33 | |||
34 | #define BTRFS_SUPER_INFO_OFFSET (16 * 1024) | ||
35 | |||
36 | #endif | 41 | #endif |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 53a7550b5c1e..e3af2c035687 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -10,9 +10,8 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | |||
10 | search_end, struct btrfs_key *ins); | 10 | search_end, struct btrfs_key *ins); |
11 | static int finish_current_insert(struct btrfs_trans_handle *trans, struct | 11 | static int finish_current_insert(struct btrfs_trans_handle *trans, struct |
12 | btrfs_root *extent_root); | 12 | btrfs_root *extent_root); |
13 | static int run_pending(struct btrfs_trans_handle *trans, struct btrfs_root | 13 | static int del_pending_extents(struct btrfs_trans_handle *trans, struct |
14 | *extent_root); | 14 | btrfs_root *extent_root); |
15 | |||
16 | /* | 15 | /* |
17 | * pending extents are blocks that we're trying to allocate in the extent | 16 | * pending extents are blocks that we're trying to allocate in the extent |
18 | * map while trying to grow the map because of other allocations. To avoid | 17 | * map while trying to grow the map because of other allocations. To avoid |
@@ -21,6 +20,7 @@ static int run_pending(struct btrfs_trans_handle *trans, struct btrfs_root | |||
21 | * manner for deletes. | 20 | * manner for deletes. |
22 | */ | 21 | */ |
23 | #define CTREE_EXTENT_PENDING_DEL 0 | 22 | #define CTREE_EXTENT_PENDING_DEL 0 |
23 | #define CTREE_EXTENT_PINNED 1 | ||
24 | 24 | ||
25 | static int inc_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root | 25 | static int inc_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root |
26 | *root, u64 blocknr) | 26 | *root, u64 blocknr) |
@@ -45,15 +45,14 @@ static int inc_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root | |||
45 | if (ret != 0) | 45 | if (ret != 0) |
46 | BUG(); | 46 | BUG(); |
47 | BUG_ON(ret != 0); | 47 | BUG_ON(ret != 0); |
48 | l = &path.nodes[0]->leaf; | 48 | l = btrfs_buffer_leaf(path.nodes[0]); |
49 | item = btrfs_item_ptr(l, path.slots[0], struct btrfs_extent_item); | 49 | item = btrfs_item_ptr(l, path.slots[0], struct btrfs_extent_item); |
50 | refs = btrfs_extent_refs(item); | 50 | refs = btrfs_extent_refs(item); |
51 | btrfs_set_extent_refs(item, refs + 1); | 51 | btrfs_set_extent_refs(item, refs + 1); |
52 | 52 | ||
53 | BUG_ON(list_empty(&path.nodes[0]->dirty)); | ||
54 | btrfs_release_path(root->fs_info->extent_root, &path); | 53 | btrfs_release_path(root->fs_info->extent_root, &path); |
55 | finish_current_insert(trans, root->fs_info->extent_root); | 54 | finish_current_insert(trans, root->fs_info->extent_root); |
56 | run_pending(trans, root->fs_info->extent_root); | 55 | del_pending_extents(trans, root->fs_info->extent_root); |
57 | return 0; | 56 | return 0; |
58 | } | 57 | } |
59 | 58 | ||
@@ -74,7 +73,7 @@ static int lookup_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root | |||
74 | 0, 0); | 73 | 0, 0); |
75 | if (ret != 0) | 74 | if (ret != 0) |
76 | BUG(); | 75 | BUG(); |
77 | l = &path.nodes[0]->leaf; | 76 | l = btrfs_buffer_leaf(path.nodes[0]); |
78 | item = btrfs_item_ptr(l, path.slots[0], struct btrfs_extent_item); | 77 | item = btrfs_item_ptr(l, path.slots[0], struct btrfs_extent_item); |
79 | *refs = btrfs_extent_refs(item); | 78 | *refs = btrfs_extent_refs(item); |
80 | btrfs_release_path(root->fs_info->extent_root, &path); | 79 | btrfs_release_path(root->fs_info->extent_root, &path); |
@@ -82,18 +81,20 @@ static int lookup_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root | |||
82 | } | 81 | } |
83 | 82 | ||
84 | int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 83 | int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
85 | struct btrfs_buffer *buf) | 84 | struct buffer_head *buf) |
86 | { | 85 | { |
87 | u64 blocknr; | 86 | u64 blocknr; |
87 | struct btrfs_node *buf_node; | ||
88 | int i; | 88 | int i; |
89 | 89 | ||
90 | if (!root->ref_cows) | 90 | if (!root->ref_cows) |
91 | return 0; | 91 | return 0; |
92 | if (btrfs_is_leaf(&buf->node)) | 92 | buf_node = btrfs_buffer_node(buf); |
93 | if (btrfs_is_leaf(buf_node)) | ||
93 | return 0; | 94 | return 0; |
94 | 95 | ||
95 | for (i = 0; i < btrfs_header_nritems(&buf->node.header); i++) { | 96 | for (i = 0; i < btrfs_header_nritems(&buf_node->header); i++) { |
96 | blocknr = btrfs_node_blockptr(&buf->node, i); | 97 | blocknr = btrfs_node_blockptr(buf_node, i); |
97 | inc_block_ref(trans, root, blocknr); | 98 | inc_block_ref(trans, root, blocknr); |
98 | } | 99 | } |
99 | return 0; | 100 | return 0; |
@@ -108,9 +109,10 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct | |||
108 | int i; | 109 | int i; |
109 | 110 | ||
110 | while(1) { | 111 | while(1) { |
111 | ret = radix_tree_gang_lookup(&root->fs_info->pinned_radix, | 112 | ret = radix_tree_gang_lookup_tag(&root->fs_info->pinned_radix, |
112 | (void **)gang, 0, | 113 | (void **)gang, 0, |
113 | ARRAY_SIZE(gang)); | 114 | ARRAY_SIZE(gang), |
115 | CTREE_EXTENT_PINNED); | ||
114 | if (!ret) | 116 | if (!ret) |
115 | break; | 117 | break; |
116 | if (!first) | 118 | if (!first) |
@@ -137,7 +139,7 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, struct | |||
137 | 139 | ||
138 | btrfs_set_extent_refs(&extent_item, 1); | 140 | btrfs_set_extent_refs(&extent_item, 1); |
139 | btrfs_set_extent_owner(&extent_item, | 141 | btrfs_set_extent_owner(&extent_item, |
140 | btrfs_header_parentid(&extent_root->node->node.header)); | 142 | btrfs_header_parentid(btrfs_buffer_header(extent_root->node))); |
141 | ins.offset = 1; | 143 | ins.offset = 1; |
142 | ins.flags = 0; | 144 | ins.flags = 0; |
143 | btrfs_set_key_type(&ins, BTRFS_EXTENT_ITEM_KEY); | 145 | btrfs_set_key_type(&ins, BTRFS_EXTENT_ITEM_KEY); |
@@ -156,11 +158,24 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, struct | |||
156 | return 0; | 158 | return 0; |
157 | } | 159 | } |
158 | 160 | ||
161 | static int pin_down_block(struct btrfs_root *root, u64 blocknr, int tag) | ||
162 | { | ||
163 | int err; | ||
164 | err = radix_tree_insert(&root->fs_info->pinned_radix, | ||
165 | blocknr, (void *)blocknr); | ||
166 | BUG_ON(err); | ||
167 | if (err) | ||
168 | return err; | ||
169 | radix_tree_tag_set(&root->fs_info->pinned_radix, blocknr, | ||
170 | tag); | ||
171 | return 0; | ||
172 | } | ||
173 | |||
159 | /* | 174 | /* |
160 | * remove an extent from the root, returns 0 on success | 175 | * remove an extent from the root, returns 0 on success |
161 | */ | 176 | */ |
162 | static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | 177 | static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root |
163 | *root, u64 blocknr, u64 num_blocks, int pin) | 178 | *root, u64 blocknr, u64 num_blocks) |
164 | { | 179 | { |
165 | struct btrfs_path path; | 180 | struct btrfs_path path; |
166 | struct btrfs_key key; | 181 | struct btrfs_key key; |
@@ -171,7 +186,6 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | |||
171 | struct btrfs_key ins; | 186 | struct btrfs_key ins; |
172 | u32 refs; | 187 | u32 refs; |
173 | 188 | ||
174 | BUG_ON(pin && num_blocks != 1); | ||
175 | key.objectid = blocknr; | 189 | key.objectid = blocknr; |
176 | key.flags = 0; | 190 | key.flags = 0; |
177 | btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); | 191 | btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); |
@@ -186,26 +200,18 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | |||
186 | printk("failed to find %Lu\n", key.objectid); | 200 | printk("failed to find %Lu\n", key.objectid); |
187 | BUG(); | 201 | BUG(); |
188 | } | 202 | } |
189 | ei = btrfs_item_ptr(&path.nodes[0]->leaf, path.slots[0], | 203 | ei = btrfs_item_ptr(btrfs_buffer_leaf(path.nodes[0]), path.slots[0], |
190 | struct btrfs_extent_item); | 204 | struct btrfs_extent_item); |
191 | BUG_ON(ei->refs == 0); | 205 | BUG_ON(ei->refs == 0); |
192 | refs = btrfs_extent_refs(ei) - 1; | 206 | refs = btrfs_extent_refs(ei) - 1; |
193 | btrfs_set_extent_refs(ei, refs); | 207 | btrfs_set_extent_refs(ei, refs); |
194 | if (refs == 0) { | 208 | if (refs == 0) { |
195 | u64 super_blocks_used; | 209 | u64 super_blocks_used; |
196 | if (pin) { | ||
197 | int err; | ||
198 | radix_tree_preload(GFP_KERNEL); | ||
199 | err = radix_tree_insert(&info->pinned_radix, | ||
200 | blocknr, (void *)blocknr); | ||
201 | BUG_ON(err); | ||
202 | radix_tree_preload_end(); | ||
203 | } | ||
204 | super_blocks_used = btrfs_super_blocks_used(info->disk_super); | 210 | super_blocks_used = btrfs_super_blocks_used(info->disk_super); |
205 | btrfs_set_super_blocks_used(info->disk_super, | 211 | btrfs_set_super_blocks_used(info->disk_super, |
206 | super_blocks_used - num_blocks); | 212 | super_blocks_used - num_blocks); |
207 | ret = btrfs_del_item(trans, extent_root, &path); | 213 | ret = btrfs_del_item(trans, extent_root, &path); |
208 | if (!pin && extent_root->fs_info->last_insert.objectid > | 214 | if (extent_root->fs_info->last_insert.objectid > |
209 | blocknr) | 215 | blocknr) |
210 | extent_root->fs_info->last_insert.objectid = blocknr; | 216 | extent_root->fs_info->last_insert.objectid = blocknr; |
211 | if (ret) | 217 | if (ret) |
@@ -224,39 +230,32 @@ static int del_pending_extents(struct btrfs_trans_handle *trans, struct | |||
224 | btrfs_root *extent_root) | 230 | btrfs_root *extent_root) |
225 | { | 231 | { |
226 | int ret; | 232 | int ret; |
227 | struct btrfs_buffer *gang[4]; | 233 | int wret; |
234 | int err = 0; | ||
235 | unsigned long gang[4]; | ||
228 | int i; | 236 | int i; |
237 | struct radix_tree_root *radix = &extent_root->fs_info->pinned_radix; | ||
229 | 238 | ||
230 | while(1) { | 239 | while(1) { |
231 | ret = radix_tree_gang_lookup_tag( | 240 | ret = radix_tree_gang_lookup_tag( |
232 | &extent_root->fs_info->cache_radix, | 241 | &extent_root->fs_info->pinned_radix, |
233 | (void **)gang, 0, | 242 | (void **)gang, 0, |
234 | ARRAY_SIZE(gang), | 243 | ARRAY_SIZE(gang), |
235 | CTREE_EXTENT_PENDING_DEL); | 244 | CTREE_EXTENT_PENDING_DEL); |
236 | if (!ret) | 245 | if (!ret) |
237 | break; | 246 | break; |
238 | for (i = 0; i < ret; i++) { | 247 | for (i = 0; i < ret; i++) { |
239 | ret = __free_extent(trans, extent_root, | 248 | radix_tree_tag_set(radix, gang[i], CTREE_EXTENT_PINNED); |
240 | gang[i]->blocknr, 1, 1); | 249 | radix_tree_tag_clear(radix, gang[i], |
241 | radix_tree_tag_clear(&extent_root->fs_info->cache_radix, | ||
242 | gang[i]->blocknr, | ||
243 | CTREE_EXTENT_PENDING_DEL); | 250 | CTREE_EXTENT_PENDING_DEL); |
244 | btrfs_block_release(extent_root, gang[i]); | 251 | wret = __free_extent(trans, extent_root, gang[i], 1); |
252 | if (wret) | ||
253 | err = wret; | ||
245 | } | 254 | } |
246 | } | 255 | } |
247 | return 0; | 256 | return err; |
248 | } | 257 | } |
249 | 258 | ||
250 | static int run_pending(struct btrfs_trans_handle *trans, struct btrfs_root | ||
251 | *extent_root) | ||
252 | { | ||
253 | while(radix_tree_tagged(&extent_root->fs_info->cache_radix, | ||
254 | CTREE_EXTENT_PENDING_DEL)) | ||
255 | del_pending_extents(trans, extent_root); | ||
256 | return 0; | ||
257 | } | ||
258 | |||
259 | |||
260 | /* | 259 | /* |
261 | * remove an extent from the root, returns 0 on success | 260 | * remove an extent from the root, returns 0 on success |
262 | */ | 261 | */ |
@@ -264,18 +263,21 @@ int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | |||
264 | *root, u64 blocknr, u64 num_blocks, int pin) | 263 | *root, u64 blocknr, u64 num_blocks, int pin) |
265 | { | 264 | { |
266 | struct btrfs_root *extent_root = root->fs_info->extent_root; | 265 | struct btrfs_root *extent_root = root->fs_info->extent_root; |
267 | struct btrfs_buffer *t; | 266 | struct buffer_head *t; |
268 | int pending_ret; | 267 | int pending_ret; |
269 | int ret; | 268 | int ret; |
270 | 269 | ||
271 | if (root == extent_root) { | 270 | if (root == extent_root) { |
272 | t = find_tree_block(root, blocknr); | 271 | t = find_tree_block(root, blocknr); |
273 | radix_tree_tag_set(&root->fs_info->cache_radix, blocknr, | 272 | pin_down_block(root, blocknr, CTREE_EXTENT_PENDING_DEL); |
274 | CTREE_EXTENT_PENDING_DEL); | ||
275 | return 0; | 273 | return 0; |
276 | } | 274 | } |
277 | ret = __free_extent(trans, root, blocknr, num_blocks, pin); | 275 | if (pin) { |
278 | pending_ret = run_pending(trans, root->fs_info->extent_root); | 276 | ret = pin_down_block(root, blocknr, CTREE_EXTENT_PINNED); |
277 | BUG_ON(ret); | ||
278 | } | ||
279 | ret = __free_extent(trans, root, blocknr, num_blocks); | ||
280 | pending_ret = del_pending_extents(trans, root->fs_info->extent_root); | ||
279 | return ret ? ret : pending_ret; | 281 | return ret ? ret : pending_ret; |
280 | } | 282 | } |
281 | 283 | ||
@@ -296,14 +298,16 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | |||
296 | int ret; | 298 | int ret; |
297 | u64 hole_size = 0; | 299 | u64 hole_size = 0; |
298 | int slot = 0; | 300 | int slot = 0; |
299 | u64 last_block; | 301 | u64 last_block = 0; |
300 | u64 test_block; | 302 | u64 test_block; |
301 | int start_found; | 303 | int start_found; |
302 | struct btrfs_leaf *l; | 304 | struct btrfs_leaf *l; |
303 | struct btrfs_root * root = orig_root->fs_info->extent_root; | 305 | struct btrfs_root * root = orig_root->fs_info->extent_root; |
304 | int total_needed = num_blocks; | 306 | int total_needed = num_blocks; |
307 | int level; | ||
305 | 308 | ||
306 | total_needed += (btrfs_header_level(&root->node->node.header) + 1) * 3; | 309 | level = btrfs_header_level(btrfs_buffer_header(root->node)); |
310 | total_needed += (level + 1) * 3; | ||
307 | if (root->fs_info->last_insert.objectid > search_start) | 311 | if (root->fs_info->last_insert.objectid > search_start) |
308 | search_start = root->fs_info->last_insert.objectid; | 312 | search_start = root->fs_info->last_insert.objectid; |
309 | 313 | ||
@@ -323,7 +327,7 @@ check_failed: | |||
323 | path.slots[0]--; | 327 | path.slots[0]--; |
324 | 328 | ||
325 | while (1) { | 329 | while (1) { |
326 | l = &path.nodes[0]->leaf; | 330 | l = btrfs_buffer_leaf(path.nodes[0]); |
327 | slot = path.slots[0]; | 331 | slot = path.slots[0]; |
328 | if (slot >= btrfs_header_nritems(&l->header)) { | 332 | if (slot >= btrfs_header_nritems(&l->header)) { |
329 | ret = btrfs_next_leaf(root, &path); | 333 | ret = btrfs_next_leaf(root, &path); |
@@ -429,7 +433,7 @@ static int alloc_extent(struct btrfs_trans_handle *trans, struct btrfs_root | |||
429 | sizeof(extent_item)); | 433 | sizeof(extent_item)); |
430 | 434 | ||
431 | finish_current_insert(trans, extent_root); | 435 | finish_current_insert(trans, extent_root); |
432 | pending_ret = run_pending(trans, extent_root); | 436 | pending_ret = del_pending_extents(trans, extent_root); |
433 | if (ret) | 437 | if (ret) |
434 | return ret; | 438 | return ret; |
435 | if (pending_ret) | 439 | if (pending_ret) |
@@ -441,16 +445,15 @@ static int alloc_extent(struct btrfs_trans_handle *trans, struct btrfs_root | |||
441 | * helper function to allocate a block for a given tree | 445 | * helper function to allocate a block for a given tree |
442 | * returns the tree buffer or NULL. | 446 | * returns the tree buffer or NULL. |
443 | */ | 447 | */ |
444 | struct btrfs_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans, | 448 | struct buffer_head *btrfs_alloc_free_block(struct btrfs_trans_handle *trans, |
445 | struct btrfs_root *root) | 449 | struct btrfs_root *root) |
446 | { | 450 | { |
447 | struct btrfs_key ins; | 451 | struct btrfs_key ins; |
448 | int ret; | 452 | int ret; |
449 | struct btrfs_buffer *buf; | 453 | struct buffer_head *buf; |
450 | 454 | ||
451 | ret = alloc_extent(trans, root, 1, 0, (unsigned long)-1, | 455 | ret = alloc_extent(trans, root, 1, 0, (unsigned long)-1, |
452 | btrfs_header_parentid(&root->node->node.header), | 456 | btrfs_header_parentid(btrfs_buffer_header(root->node)), &ins); |
453 | &ins); | ||
454 | if (ret) { | 457 | if (ret) { |
455 | BUG(); | 458 | BUG(); |
456 | return NULL; | 459 | return NULL; |
@@ -467,13 +470,13 @@ struct btrfs_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans, | |||
467 | static int walk_down_tree(struct btrfs_trans_handle *trans, struct btrfs_root | 470 | static int walk_down_tree(struct btrfs_trans_handle *trans, struct btrfs_root |
468 | *root, struct btrfs_path *path, int *level) | 471 | *root, struct btrfs_path *path, int *level) |
469 | { | 472 | { |
470 | struct btrfs_buffer *next; | 473 | struct buffer_head *next; |
471 | struct btrfs_buffer *cur; | 474 | struct buffer_head *cur; |
472 | u64 blocknr; | 475 | u64 blocknr; |
473 | int ret; | 476 | int ret; |
474 | u32 refs; | 477 | u32 refs; |
475 | 478 | ||
476 | ret = lookup_block_ref(trans, root, path->nodes[*level]->blocknr, | 479 | ret = lookup_block_ref(trans, root, path->nodes[*level]->b_blocknr, |
477 | &refs); | 480 | &refs); |
478 | BUG_ON(ret); | 481 | BUG_ON(ret); |
479 | if (refs > 1) | 482 | if (refs > 1) |
@@ -484,9 +487,10 @@ static int walk_down_tree(struct btrfs_trans_handle *trans, struct btrfs_root | |||
484 | while(*level > 0) { | 487 | while(*level > 0) { |
485 | cur = path->nodes[*level]; | 488 | cur = path->nodes[*level]; |
486 | if (path->slots[*level] >= | 489 | if (path->slots[*level] >= |
487 | btrfs_header_nritems(&cur->node.header)) | 490 | btrfs_header_nritems(btrfs_buffer_header(cur))) |
488 | break; | 491 | break; |
489 | blocknr = btrfs_node_blockptr(&cur->node, path->slots[*level]); | 492 | blocknr = btrfs_node_blockptr(btrfs_buffer_node(cur), |
493 | path->slots[*level]); | ||
490 | ret = lookup_block_ref(trans, root, blocknr, &refs); | 494 | ret = lookup_block_ref(trans, root, blocknr, &refs); |
491 | if (refs != 1 || *level == 1) { | 495 | if (refs != 1 || *level == 1) { |
492 | path->slots[*level]++; | 496 | path->slots[*level]++; |
@@ -499,12 +503,12 @@ static int walk_down_tree(struct btrfs_trans_handle *trans, struct btrfs_root | |||
499 | if (path->nodes[*level-1]) | 503 | if (path->nodes[*level-1]) |
500 | btrfs_block_release(root, path->nodes[*level-1]); | 504 | btrfs_block_release(root, path->nodes[*level-1]); |
501 | path->nodes[*level-1] = next; | 505 | path->nodes[*level-1] = next; |
502 | *level = btrfs_header_level(&next->node.header); | 506 | *level = btrfs_header_level(btrfs_buffer_header(next)); |
503 | path->slots[*level] = 0; | 507 | path->slots[*level] = 0; |
504 | } | 508 | } |
505 | out: | 509 | out: |
506 | ret = btrfs_free_extent(trans, root, path->nodes[*level]->blocknr, 1, | 510 | ret = btrfs_free_extent(trans, root, path->nodes[*level]->b_blocknr, |
507 | 1); | 511 | 1, 1); |
508 | btrfs_block_release(root, path->nodes[*level]); | 512 | btrfs_block_release(root, path->nodes[*level]); |
509 | path->nodes[*level] = NULL; | 513 | path->nodes[*level] = NULL; |
510 | *level += 1; | 514 | *level += 1; |
@@ -525,14 +529,14 @@ static int walk_up_tree(struct btrfs_trans_handle *trans, struct btrfs_root | |||
525 | int ret; | 529 | int ret; |
526 | for(i = *level; i < BTRFS_MAX_LEVEL - 1 && path->nodes[i]; i++) { | 530 | for(i = *level; i < BTRFS_MAX_LEVEL - 1 && path->nodes[i]; i++) { |
527 | slot = path->slots[i]; | 531 | slot = path->slots[i]; |
528 | if (slot < | 532 | if (slot < btrfs_header_nritems( |
529 | btrfs_header_nritems(&path->nodes[i]->node.header)- 1) { | 533 | btrfs_buffer_header(path->nodes[i])) - 1) { |
530 | path->slots[i]++; | 534 | path->slots[i]++; |
531 | *level = i; | 535 | *level = i; |
532 | return 0; | 536 | return 0; |
533 | } else { | 537 | } else { |
534 | ret = btrfs_free_extent(trans, root, | 538 | ret = btrfs_free_extent(trans, root, |
535 | path->nodes[*level]->blocknr, | 539 | path->nodes[*level]->b_blocknr, |
536 | 1, 1); | 540 | 1, 1); |
537 | btrfs_block_release(root, path->nodes[*level]); | 541 | btrfs_block_release(root, path->nodes[*level]); |
538 | path->nodes[*level] = NULL; | 542 | path->nodes[*level] = NULL; |
@@ -549,7 +553,7 @@ static int walk_up_tree(struct btrfs_trans_handle *trans, struct btrfs_root | |||
549 | * decremented. | 553 | * decremented. |
550 | */ | 554 | */ |
551 | int btrfs_drop_snapshot(struct btrfs_trans_handle *trans, struct btrfs_root | 555 | int btrfs_drop_snapshot(struct btrfs_trans_handle *trans, struct btrfs_root |
552 | *root, struct btrfs_buffer *snap) | 556 | *root, struct buffer_head *snap) |
553 | { | 557 | { |
554 | int ret = 0; | 558 | int ret = 0; |
555 | int wret; | 559 | int wret; |
@@ -560,7 +564,7 @@ int btrfs_drop_snapshot(struct btrfs_trans_handle *trans, struct btrfs_root | |||
560 | 564 | ||
561 | btrfs_init_path(&path); | 565 | btrfs_init_path(&path); |
562 | 566 | ||
563 | level = btrfs_header_level(&snap->node.header); | 567 | level = btrfs_header_level(btrfs_buffer_header(snap)); |
564 | orig_level = level; | 568 | orig_level = level; |
565 | path.nodes[level] = snap; | 569 | path.nodes[level] = snap; |
566 | path.slots[level] = 0; | 570 | path.slots[level] = 0; |
diff --git a/fs/btrfs/hash.c b/fs/btrfs/hash.c index 6c2a71a46c7d..22519b8e0cf2 100644 --- a/fs/btrfs/hash.c +++ b/fs/btrfs/hash.c | |||
@@ -10,6 +10,7 @@ | |||
10 | * License. | 10 | * License. |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/types.h> | ||
13 | #define DELTA 0x9E3779B9 | 14 | #define DELTA 0x9E3779B9 |
14 | 15 | ||
15 | static void TEA_transform(__u32 buf[2], __u32 const in[]) | 16 | static void TEA_transform(__u32 buf[2], __u32 const in[]) |
@@ -63,6 +64,14 @@ int btrfs_name_hash(const char *name, int len, u64 *hash_result) | |||
63 | const char *p; | 64 | const char *p; |
64 | __u32 in[8], buf[2]; | 65 | __u32 in[8], buf[2]; |
65 | 66 | ||
67 | if (len == 1 && *name == '.') { | ||
68 | *hash_result = 1; | ||
69 | return 0; | ||
70 | } else if (len == 2 && name[0] == '.' && name[1] == '.') { | ||
71 | *hash_result = 2; | ||
72 | return 0; | ||
73 | } | ||
74 | |||
66 | /* Initialize the default seed for the hash checksum functions */ | 75 | /* Initialize the default seed for the hash checksum functions */ |
67 | buf[0] = 0x67452301; | 76 | buf[0] = 0x67452301; |
68 | buf[1] = 0xefcdab89; | 77 | buf[1] = 0xefcdab89; |
diff --git a/fs/btrfs/inode-map.c b/fs/btrfs/inode-map.c index c7fda3bf7b21..c45aec258bd5 100644 --- a/fs/btrfs/inode-map.c +++ b/fs/btrfs/inode-map.c | |||
@@ -15,7 +15,7 @@ int btrfs_find_free_objectid(struct btrfs_trans_handle *trans, | |||
15 | int ret; | 15 | int ret; |
16 | u64 hole_size = 0; | 16 | u64 hole_size = 0; |
17 | int slot = 0; | 17 | int slot = 0; |
18 | u64 last_ino; | 18 | u64 last_ino = 0; |
19 | int start_found; | 19 | int start_found; |
20 | struct btrfs_leaf *l; | 20 | struct btrfs_leaf *l; |
21 | struct btrfs_root *root = fs_root->fs_info->inode_root; | 21 | struct btrfs_root *root = fs_root->fs_info->inode_root; |
@@ -40,7 +40,7 @@ int btrfs_find_free_objectid(struct btrfs_trans_handle *trans, | |||
40 | path.slots[0]--; | 40 | path.slots[0]--; |
41 | 41 | ||
42 | while (1) { | 42 | while (1) { |
43 | l = &path.nodes[0]->leaf; | 43 | l = btrfs_buffer_leaf(path.nodes[0]); |
44 | slot = path.slots[0]; | 44 | slot = path.slots[0]; |
45 | if (slot >= btrfs_header_nritems(&l->header)) { | 45 | if (slot >= btrfs_header_nritems(&l->header)) { |
46 | ret = btrfs_next_leaf(root, &path); | 46 | ret = btrfs_next_leaf(root, &path); |
@@ -105,8 +105,8 @@ int btrfs_insert_inode_map(struct btrfs_trans_handle *trans, | |||
105 | if (ret) | 105 | if (ret) |
106 | goto out; | 106 | goto out; |
107 | 107 | ||
108 | inode_item = btrfs_item_ptr(&path.nodes[0]->leaf, path.slots[0], | 108 | inode_item = btrfs_item_ptr(btrfs_buffer_leaf(path.nodes[0]), |
109 | struct btrfs_inode_map_item); | 109 | path.slots[0], struct btrfs_inode_map_item); |
110 | btrfs_cpu_key_to_disk(&inode_item->key, location); | 110 | btrfs_cpu_key_to_disk(&inode_item->key, location); |
111 | out: | 111 | out: |
112 | btrfs_release_path(inode_root, &path); | 112 | btrfs_release_path(inode_root, &path); |
diff --git a/fs/btrfs/print-tree.c b/fs/btrfs/print-tree.c index aa2d3fac8804..c8ee938c1251 100644 --- a/fs/btrfs/print-tree.c +++ b/fs/btrfs/print-tree.c | |||
@@ -17,7 +17,6 @@ void btrfs_print_leaf(struct btrfs_root *root, struct btrfs_leaf *l) | |||
17 | printk("leaf %Lu total ptrs %d free space %d\n", | 17 | printk("leaf %Lu total ptrs %d free space %d\n", |
18 | btrfs_header_blocknr(&l->header), nr, | 18 | btrfs_header_blocknr(&l->header), nr, |
19 | btrfs_leaf_free_space(root, l)); | 19 | btrfs_leaf_free_space(root, l)); |
20 | fflush(stdout); | ||
21 | for (i = 0 ; i < nr ; i++) { | 20 | for (i = 0 ; i < nr ; i++) { |
22 | item = l->items + i; | 21 | item = l->items + i; |
23 | type = btrfs_disk_key_type(&item->key); | 22 | type = btrfs_disk_key_type(&item->key); |
@@ -67,10 +66,10 @@ void btrfs_print_leaf(struct btrfs_root *root, struct btrfs_leaf *l) | |||
67 | btrfs_leaf_data(l) + btrfs_item_offset(item)); | 66 | btrfs_leaf_data(l) + btrfs_item_offset(item)); |
68 | break; | 67 | break; |
69 | }; | 68 | }; |
70 | fflush(stdout); | ||
71 | } | 69 | } |
72 | } | 70 | } |
73 | void btrfs_print_tree(struct btrfs_root *root, struct btrfs_buffer *t) | 71 | |
72 | void btrfs_print_tree(struct btrfs_root *root, struct buffer_head *t) | ||
74 | { | 73 | { |
75 | int i; | 74 | int i; |
76 | u32 nr; | 75 | u32 nr; |
@@ -78,16 +77,16 @@ void btrfs_print_tree(struct btrfs_root *root, struct btrfs_buffer *t) | |||
78 | 77 | ||
79 | if (!t) | 78 | if (!t) |
80 | return; | 79 | return; |
81 | c = &t->node; | 80 | c = btrfs_buffer_node(t); |
82 | nr = btrfs_header_nritems(&c->header); | 81 | nr = btrfs_header_nritems(&c->header); |
83 | if (btrfs_is_leaf(c)) { | 82 | if (btrfs_is_leaf(c)) { |
84 | btrfs_print_leaf(root, (struct btrfs_leaf *)c); | 83 | btrfs_print_leaf(root, (struct btrfs_leaf *)c); |
85 | return; | 84 | return; |
86 | } | 85 | } |
87 | printk("node %Lu level %d total ptrs %d free spc %u\n", t->blocknr, | 86 | printk("node %Lu level %d total ptrs %d free spc %u\n", |
88 | btrfs_header_level(&c->header), nr, | 87 | btrfs_header_blocknr(&c->header), |
89 | (u32)BTRFS_NODEPTRS_PER_BLOCK(root) - nr); | 88 | btrfs_header_level(&c->header), nr, |
90 | fflush(stdout); | 89 | (u32)BTRFS_NODEPTRS_PER_BLOCK(root) - nr); |
91 | for (i = 0; i < nr; i++) { | 90 | for (i = 0; i < nr; i++) { |
92 | printk("\tkey %d (%Lu %u %Lu) block %Lu\n", | 91 | printk("\tkey %d (%Lu %u %Lu) block %Lu\n", |
93 | i, | 92 | i, |
@@ -95,12 +94,11 @@ void btrfs_print_tree(struct btrfs_root *root, struct btrfs_buffer *t) | |||
95 | c->ptrs[i].key.flags, | 94 | c->ptrs[i].key.flags, |
96 | c->ptrs[i].key.offset, | 95 | c->ptrs[i].key.offset, |
97 | btrfs_node_blockptr(c, i)); | 96 | btrfs_node_blockptr(c, i)); |
98 | fflush(stdout); | ||
99 | } | 97 | } |
100 | for (i = 0; i < nr; i++) { | 98 | for (i = 0; i < nr; i++) { |
101 | struct btrfs_buffer *next_buf = read_tree_block(root, | 99 | struct buffer_head *next_buf = read_tree_block(root, |
102 | btrfs_node_blockptr(c, i)); | 100 | btrfs_node_blockptr(c, i)); |
103 | struct btrfs_node *next = &next_buf->node; | 101 | struct btrfs_node *next = btrfs_buffer_node(next_buf); |
104 | if (btrfs_is_leaf(next) && | 102 | if (btrfs_is_leaf(next) && |
105 | btrfs_header_level(&c->header) != 1) | 103 | btrfs_header_level(&c->header) != 1) |
106 | BUG(); | 104 | BUG(); |
diff --git a/fs/btrfs/print-tree.h b/fs/btrfs/print-tree.h index 0882ca904eca..396041a05cfa 100644 --- a/fs/btrfs/print-tree.h +++ b/fs/btrfs/print-tree.h | |||
@@ -1,5 +1,5 @@ | |||
1 | #ifndef __PRINT_TREE_ | 1 | #ifndef __PRINT_TREE_ |
2 | #define __PRINT_TREE_ | 2 | #define __PRINT_TREE_ |
3 | void btrfs_print_leaf(struct btrfs_root *root, struct btrfs_leaf *l); | 3 | void btrfs_print_leaf(struct btrfs_root *root, struct btrfs_leaf *l); |
4 | void btrfs_print_tree(struct btrfs_root *root, struct btrfs_buffer *t); | 4 | void btrfs_print_tree(struct btrfs_root *root, struct buffer_head *t); |
5 | #endif | 5 | #endif |
diff --git a/fs/btrfs/root-tree.c b/fs/btrfs/root-tree.c index 52c83be4b307..a4554c007ef7 100644 --- a/fs/btrfs/root-tree.c +++ b/fs/btrfs/root-tree.c | |||
@@ -21,7 +21,7 @@ int btrfs_find_last_root(struct btrfs_root *root, u64 objectid, | |||
21 | if (ret < 0) | 21 | if (ret < 0) |
22 | goto out; | 22 | goto out; |
23 | BUG_ON(ret == 0); | 23 | BUG_ON(ret == 0); |
24 | l = &path.nodes[0]->leaf; | 24 | l = btrfs_buffer_leaf(path.nodes[0]); |
25 | BUG_ON(path.slots[0] == 0); | 25 | BUG_ON(path.slots[0] == 0); |
26 | slot = path.slots[0] - 1; | 26 | slot = path.slots[0] - 1; |
27 | if (btrfs_disk_key_objectid(&l->items[slot].key) != objectid) { | 27 | if (btrfs_disk_key_objectid(&l->items[slot].key) != objectid) { |
@@ -51,7 +51,7 @@ int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root | |||
51 | if (ret < 0) | 51 | if (ret < 0) |
52 | goto out; | 52 | goto out; |
53 | BUG_ON(ret != 0); | 53 | BUG_ON(ret != 0); |
54 | l = &path.nodes[0]->leaf; | 54 | l = btrfs_buffer_leaf(path.nodes[0]); |
55 | slot = path.slots[0]; | 55 | slot = path.slots[0]; |
56 | memcpy(btrfs_item_ptr(l, slot, struct btrfs_root_item), item, | 56 | memcpy(btrfs_item_ptr(l, slot, struct btrfs_root_item), item, |
57 | sizeof(*item)); | 57 | sizeof(*item)); |
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 4ae76044aeab..ccc056aad692 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -1,4 +1,5 @@ | |||
1 | #include <linux/module.h> | 1 | #include <linux/module.h> |
2 | #include <linux/buffer_head.h> | ||
2 | #include <linux/fs.h> | 3 | #include <linux/fs.h> |
3 | #include <linux/pagemap.h> | 4 | #include <linux/pagemap.h> |
4 | #include <linux/highmem.h> | 5 | #include <linux/highmem.h> |
@@ -8,13 +9,18 @@ | |||
8 | #include <linux/smp_lock.h> | 9 | #include <linux/smp_lock.h> |
9 | #include <linux/backing-dev.h> | 10 | #include <linux/backing-dev.h> |
10 | #include "ctree.h" | 11 | #include "ctree.h" |
12 | #include "disk-io.h" | ||
11 | 13 | ||
12 | #define BTRFS_SUPER_MAGIC 0x9123682E | 14 | #define BTRFS_SUPER_MAGIC 0x9123682E |
15 | |||
16 | static struct inode_operations btrfs_dir_inode_operations; | ||
17 | static struct super_operations btrfs_super_ops; | ||
18 | static struct file_operations btrfs_dir_file_operations; | ||
19 | |||
13 | #if 0 | 20 | #if 0 |
14 | /* some random number */ | 21 | /* some random number */ |
15 | 22 | ||
16 | static struct super_operations ramfs_ops; | 23 | static struct super_operations ramfs_ops; |
17 | static struct inode_operations ramfs_dir_inode_operations; | ||
18 | 24 | ||
19 | static struct backing_dev_info ramfs_backing_dev_info = { | 25 | static struct backing_dev_info ramfs_backing_dev_info = { |
20 | .ra_pages = 0, /* No readahead */ | 26 | .ra_pages = 0, /* No readahead */ |
@@ -129,46 +135,243 @@ static struct inode_operations ramfs_dir_inode_operations = { | |||
129 | }; | 135 | }; |
130 | #endif | 136 | #endif |
131 | 137 | ||
132 | struct inode *btrfs_get_inode(struct super_block *sb, int mode, dev_t dev) | 138 | static void btrfs_read_locked_inode(struct inode *inode) |
133 | { | 139 | { |
134 | struct inode * inode = new_inode(sb); | 140 | struct btrfs_path path; |
141 | struct btrfs_inode_item *inode_item; | ||
142 | struct btrfs_root *root = btrfs_sb(inode->i_sb); | ||
143 | int ret; | ||
144 | printk("read locked inode %lu\n", inode->i_ino); | ||
145 | btrfs_init_path(&path); | ||
146 | ret = btrfs_lookup_inode(NULL, root, &path, inode->i_ino, 0); | ||
147 | if (ret) { | ||
148 | make_bad_inode(inode); | ||
149 | return; | ||
150 | } | ||
151 | inode_item = btrfs_item_ptr(btrfs_buffer_leaf(path.nodes[0]), | ||
152 | path.slots[0], | ||
153 | struct btrfs_inode_item); | ||
135 | 154 | ||
136 | if (inode) { | 155 | printk("found locked inode %lu\n", inode->i_ino); |
137 | inode->i_mode = mode; | 156 | inode->i_mode = btrfs_inode_mode(inode_item); |
138 | inode->i_uid = current->fsuid; | 157 | inode->i_nlink = btrfs_inode_nlink(inode_item); |
139 | inode->i_gid = current->fsgid; | 158 | inode->i_uid = btrfs_inode_uid(inode_item); |
140 | inode->i_blocks = 0; | 159 | inode->i_gid = btrfs_inode_gid(inode_item); |
141 | inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; | 160 | inode->i_size = btrfs_inode_size(inode_item); |
161 | inode->i_atime.tv_sec = btrfs_timespec_sec(&inode_item->atime); | ||
162 | inode->i_atime.tv_nsec = btrfs_timespec_nsec(&inode_item->atime); | ||
163 | inode->i_mtime.tv_sec = btrfs_timespec_sec(&inode_item->mtime); | ||
164 | inode->i_mtime.tv_nsec = btrfs_timespec_nsec(&inode_item->mtime); | ||
165 | inode->i_ctime.tv_sec = btrfs_timespec_sec(&inode_item->ctime); | ||
166 | inode->i_ctime.tv_nsec = btrfs_timespec_nsec(&inode_item->ctime); | ||
167 | inode->i_blocks = btrfs_inode_nblocks(inode_item); | ||
168 | inode->i_generation = btrfs_inode_generation(inode_item); | ||
169 | printk("about to release\n"); | ||
170 | btrfs_release_path(root, &path); | ||
171 | switch (inode->i_mode & S_IFMT) { | ||
172 | #if 0 | ||
173 | default: | ||
174 | init_special_inode(inode, inode->i_mode, | ||
175 | btrfs_inode_rdev(inode_item)); | ||
176 | break; | ||
177 | #endif | ||
178 | case S_IFREG: | ||
179 | printk("inode %lu now a file\n", inode->i_ino); | ||
180 | break; | ||
181 | case S_IFDIR: | ||
182 | printk("inode %lu now a directory\n", inode->i_ino); | ||
183 | inode->i_op = &btrfs_dir_inode_operations; | ||
184 | inode->i_fop = &btrfs_dir_file_operations; | ||
185 | break; | ||
186 | case S_IFLNK: | ||
187 | printk("inode %lu now a link\n", inode->i_ino); | ||
188 | // inode->i_op = &page_symlink_inode_operations; | ||
189 | break; | ||
142 | } | 190 | } |
143 | return inode; | 191 | printk("returning!\n"); |
192 | return; | ||
144 | } | 193 | } |
145 | 194 | ||
146 | static struct super_operations btrfs_ops = { | 195 | static int btrfs_inode_by_name(struct inode *dir, struct dentry *dentry, |
147 | .statfs = simple_statfs, | 196 | ino_t *ino) |
148 | .drop_inode = generic_delete_inode, | 197 | { |
149 | }; | 198 | const char *name = dentry->d_name.name; |
199 | int namelen = dentry->d_name.len; | ||
200 | struct btrfs_dir_item *di; | ||
201 | struct btrfs_path path; | ||
202 | struct btrfs_root *root = btrfs_sb(dir->i_sb); | ||
203 | int ret; | ||
204 | |||
205 | btrfs_init_path(&path); | ||
206 | ret = btrfs_lookup_dir_item(NULL, root, &path, dir->i_ino, name, | ||
207 | namelen, 0); | ||
208 | if (ret) { | ||
209 | *ino = 0; | ||
210 | goto out; | ||
211 | } | ||
212 | di = btrfs_item_ptr(btrfs_buffer_leaf(path.nodes[0]), path.slots[0], | ||
213 | struct btrfs_dir_item); | ||
214 | *ino = btrfs_dir_objectid(di); | ||
215 | out: | ||
216 | btrfs_release_path(root, &path); | ||
217 | return ret; | ||
218 | } | ||
219 | |||
220 | static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry, | ||
221 | struct nameidata *nd) | ||
222 | { | ||
223 | struct inode * inode; | ||
224 | ino_t ino; | ||
225 | int ret; | ||
226 | |||
227 | if (dentry->d_name.len > BTRFS_NAME_LEN) | ||
228 | return ERR_PTR(-ENAMETOOLONG); | ||
229 | |||
230 | ret = btrfs_inode_by_name(dir, dentry, &ino); | ||
231 | if (ret < 0) | ||
232 | return ERR_PTR(ret); | ||
233 | inode = NULL; | ||
234 | if (ino) { | ||
235 | printk("lookup on %.*s returns %lu\n", dentry->d_name.len, dentry->d_name.name, ino); | ||
236 | inode = iget(dir->i_sb, ino); | ||
237 | if (!inode) | ||
238 | return ERR_PTR(-EACCES); | ||
239 | } | ||
240 | return d_splice_alias(inode, dentry); | ||
241 | } | ||
242 | |||
243 | static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | ||
244 | { | ||
245 | struct inode *inode = filp->f_path.dentry->d_inode; | ||
246 | struct btrfs_root *root = btrfs_sb(inode->i_sb); | ||
247 | struct btrfs_item *item; | ||
248 | struct btrfs_dir_item *di; | ||
249 | struct btrfs_key key; | ||
250 | struct btrfs_path path; | ||
251 | int ret; | ||
252 | u32 nritems; | ||
253 | struct btrfs_leaf *leaf; | ||
254 | int slot; | ||
255 | int advance; | ||
256 | unsigned char d_type = DT_UNKNOWN; | ||
257 | int over; | ||
258 | |||
259 | key.objectid = inode->i_ino; | ||
260 | printk("readdir on dir %Lu pos %Lu\n", key.objectid, filp->f_pos); | ||
261 | key.flags = 0; | ||
262 | btrfs_set_key_type(&key, BTRFS_DIR_ITEM_KEY); | ||
263 | key.offset = filp->f_pos; | ||
264 | btrfs_init_path(&path); | ||
265 | ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0); | ||
266 | if (ret < 0) { | ||
267 | goto err; | ||
268 | } | ||
269 | printk("first ret %d\n", ret); | ||
270 | advance = filp->f_pos > 0 && ret != 0; | ||
271 | while(1) { | ||
272 | leaf = btrfs_buffer_leaf(path.nodes[0]); | ||
273 | nritems = btrfs_header_nritems(&leaf->header); | ||
274 | slot = path.slots[0]; | ||
275 | printk("leaf %Lu nritems %lu slot %d\n", path.nodes[0]->b_blocknr, nritems, slot); | ||
276 | if (advance) { | ||
277 | printk("advancing!\n"); | ||
278 | if (slot == nritems -1) { | ||
279 | ret = btrfs_next_leaf(root, &path); | ||
280 | if (ret) | ||
281 | break; | ||
282 | leaf = btrfs_buffer_leaf(path.nodes[0]); | ||
283 | nritems = btrfs_header_nritems(&leaf->header); | ||
284 | slot = path.slots[0]; | ||
285 | printk("2leaf %Lu nritems %lu slot %d\n", path.nodes[0]->b_blocknr, nritems, slot); | ||
286 | } else { | ||
287 | slot++; | ||
288 | path.slots[0]++; | ||
289 | } | ||
290 | } | ||
291 | advance = 1; | ||
292 | item = leaf->items + slot; | ||
293 | printk("item key %Lu %u %Lu\n", btrfs_disk_key_objectid(&item->key), | ||
294 | btrfs_disk_key_flags(&item->key), btrfs_disk_key_offset(&item->key)); | ||
295 | if (btrfs_disk_key_objectid(&item->key) != key.objectid) | ||
296 | break; | ||
297 | if (btrfs_disk_key_type(&item->key) != BTRFS_DIR_ITEM_KEY) | ||
298 | continue; | ||
299 | di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item); | ||
300 | printk("filldir name %.*s, objectid %Lu\n", btrfs_dir_name_len(di), | ||
301 | (const char *)(di + 1), btrfs_dir_objectid(di)); | ||
302 | over = filldir(dirent, (const char *)(di + 1), | ||
303 | btrfs_dir_name_len(di), | ||
304 | btrfs_disk_key_offset(&item->key), | ||
305 | btrfs_dir_objectid(di), d_type); | ||
306 | if (over) | ||
307 | break; | ||
308 | filp->f_pos = btrfs_disk_key_offset(&item->key) + 1; | ||
309 | } | ||
310 | printk("filldir all done\n"); | ||
311 | ret = 0; | ||
312 | err: | ||
313 | btrfs_release_path(root, &path); | ||
314 | return ret; | ||
315 | } | ||
316 | |||
317 | static void btrfs_put_super (struct super_block * sb) | ||
318 | { | ||
319 | struct btrfs_root *root = btrfs_sb(sb); | ||
320 | int ret; | ||
321 | |||
322 | ret = close_ctree(root); | ||
323 | if (ret) { | ||
324 | printk("close ctree returns %d\n", ret); | ||
325 | } | ||
326 | sb->s_fs_info = NULL; | ||
327 | } | ||
150 | 328 | ||
151 | static int btrfs_fill_super(struct super_block * sb, void * data, int silent) | 329 | static int btrfs_fill_super(struct super_block * sb, void * data, int silent) |
152 | { | 330 | { |
153 | struct inode * inode; | 331 | struct inode * inode; |
154 | struct dentry * root; | 332 | struct dentry * root_dentry; |
333 | struct btrfs_super_block *disk_super; | ||
334 | struct buffer_head *bh; | ||
335 | struct btrfs_root *root; | ||
155 | 336 | ||
156 | sb->s_maxbytes = MAX_LFS_FILESIZE; | 337 | sb->s_maxbytes = MAX_LFS_FILESIZE; |
157 | sb->s_blocksize = PAGE_CACHE_SIZE; | 338 | sb->s_blocksize = PAGE_CACHE_SIZE; |
158 | sb->s_blocksize_bits = PAGE_CACHE_SHIFT; | 339 | sb->s_blocksize_bits = PAGE_CACHE_SHIFT; |
159 | sb->s_magic = BTRFS_SUPER_MAGIC; | 340 | sb->s_magic = BTRFS_SUPER_MAGIC; |
160 | sb->s_op = &btrfs_ops; | 341 | sb->s_op = &btrfs_super_ops; |
161 | sb->s_time_gran = 1; | 342 | sb->s_time_gran = 1; |
162 | inode = btrfs_get_inode(sb, S_IFDIR | 0755, 0); | 343 | |
344 | bh = sb_bread(sb, BTRFS_SUPER_INFO_OFFSET / sb->s_blocksize); | ||
345 | if (!bh) { | ||
346 | printk("btrfs: unable to read on disk super\n"); | ||
347 | return -EIO; | ||
348 | } | ||
349 | disk_super = (struct btrfs_super_block *)bh->b_data; | ||
350 | root = open_ctree(sb, bh, disk_super); | ||
351 | sb->s_fs_info = root; | ||
352 | if (!root) { | ||
353 | printk("btrfs: open_ctree failed\n"); | ||
354 | return -EIO; | ||
355 | } | ||
356 | printk("read in super total blocks %Lu root %Lu\n", | ||
357 | btrfs_super_total_blocks(disk_super), | ||
358 | btrfs_super_root_dir(disk_super)); | ||
359 | |||
360 | inode = iget_locked(sb, btrfs_super_root_dir(disk_super)); | ||
163 | if (!inode) | 361 | if (!inode) |
164 | return -ENOMEM; | 362 | return -ENOMEM; |
363 | if (inode->i_state & I_NEW) { | ||
364 | btrfs_read_locked_inode(inode); | ||
365 | unlock_new_inode(inode); | ||
366 | } | ||
165 | 367 | ||
166 | root = d_alloc_root(inode); | 368 | root_dentry = d_alloc_root(inode); |
167 | if (!root) { | 369 | if (!root_dentry) { |
168 | iput(inode); | 370 | iput(inode); |
169 | return -ENOMEM; | 371 | return -ENOMEM; |
170 | } | 372 | } |
171 | sb->s_root = root; | 373 | sb->s_root = root_dentry; |
374 | |||
172 | return 0; | 375 | return 0; |
173 | } | 376 | } |
174 | 377 | ||
@@ -187,6 +390,24 @@ static struct file_system_type btrfs_fs_type = { | |||
187 | .fs_flags = FS_REQUIRES_DEV, | 390 | .fs_flags = FS_REQUIRES_DEV, |
188 | }; | 391 | }; |
189 | 392 | ||
393 | static struct super_operations btrfs_super_ops = { | ||
394 | .statfs = simple_statfs, | ||
395 | .drop_inode = generic_delete_inode, | ||
396 | .put_super = btrfs_put_super, | ||
397 | .read_inode = btrfs_read_locked_inode, | ||
398 | }; | ||
399 | |||
400 | static struct inode_operations btrfs_dir_inode_operations = { | ||
401 | .lookup = btrfs_lookup, | ||
402 | }; | ||
403 | |||
404 | static struct file_operations btrfs_dir_file_operations = { | ||
405 | .llseek = generic_file_llseek, | ||
406 | .read = generic_read_dir, | ||
407 | .readdir = btrfs_readdir, | ||
408 | }; | ||
409 | |||
410 | |||
190 | static int __init init_btrfs_fs(void) | 411 | static int __init init_btrfs_fs(void) |
191 | { | 412 | { |
192 | printk("btrfs loaded!\n"); | 413 | printk("btrfs loaded!\n"); |
diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h index 3adb6e69fe43..9ab27b7491c5 100644 --- a/fs/btrfs/transaction.h +++ b/fs/btrfs/transaction.h | |||
@@ -10,7 +10,7 @@ struct btrfs_trans_handle { | |||
10 | static inline struct btrfs_trans_handle * | 10 | static inline struct btrfs_trans_handle * |
11 | btrfs_start_transaction(struct btrfs_root *root, int num_blocks) | 11 | btrfs_start_transaction(struct btrfs_root *root, int num_blocks) |
12 | { | 12 | { |
13 | struct btrfs_trans_handle *h = malloc(sizeof(*h)); | 13 | struct btrfs_trans_handle *h = kmalloc(sizeof(*h), GFP_NOFS); |
14 | h->transid = root->root_key.offset; | 14 | h->transid = root->root_key.offset; |
15 | h->blocks_reserved = num_blocks; | 15 | h->blocks_reserved = num_blocks; |
16 | h->blocks_used = 0; | 16 | h->blocks_used = 0; |
@@ -21,7 +21,7 @@ static inline void btrfs_free_transaction(struct btrfs_root *root, | |||
21 | struct btrfs_trans_handle *handle) | 21 | struct btrfs_trans_handle *handle) |
22 | { | 22 | { |
23 | memset(handle, 0, sizeof(*handle)); | 23 | memset(handle, 0, sizeof(*handle)); |
24 | free(handle); | 24 | kfree(handle); |
25 | } | 25 | } |
26 | 26 | ||
27 | #endif | 27 | #endif |