diff options
-rw-r--r-- | fs/btrfs/Makefile | 4 | ||||
-rw-r--r-- | fs/btrfs/TODO | 2 | ||||
-rw-r--r-- | fs/btrfs/ctree.c | 204 | ||||
-rw-r--r-- | fs/btrfs/ctree.h | 63 | ||||
-rw-r--r-- | fs/btrfs/debug-tree.c | 1 | ||||
-rw-r--r-- | fs/btrfs/dir-item.c | 20 | ||||
-rw-r--r-- | fs/btrfs/dir-test.c | 70 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 60 | ||||
-rw-r--r-- | fs/btrfs/disk-io.h | 16 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 135 | ||||
-rw-r--r-- | fs/btrfs/inode-item.c | 15 | ||||
-rw-r--r-- | fs/btrfs/print-tree.h | 4 | ||||
-rw-r--r-- | fs/btrfs/quick-test.c | 23 | ||||
-rw-r--r-- | fs/btrfs/random-test.c | 62 | ||||
-rw-r--r-- | fs/btrfs/root-tree.c | 23 | ||||
-rw-r--r-- | fs/btrfs/transaction.h | 27 |
16 files changed, 426 insertions, 303 deletions
diff --git a/fs/btrfs/Makefile b/fs/btrfs/Makefile index 36964f54bb47..76bcd87d8575 100644 --- a/fs/btrfs/Makefile +++ b/fs/btrfs/Makefile | |||
@@ -1,5 +1,5 @@ | |||
1 | CC=gcc | 1 | CC=gcc |
2 | CFLAGS = -g -Wall | 2 | CFLAGS = -g -Wall -Werror |
3 | headers = radix-tree.h ctree.h disk-io.h kerncompat.h print-tree.h list.h | 3 | headers = radix-tree.h ctree.h disk-io.h kerncompat.h print-tree.h list.h |
4 | objects = ctree.o disk-io.o radix-tree.o mkfs.o extent-tree.o print-tree.o \ | 4 | objects = ctree.o disk-io.o radix-tree.o mkfs.o extent-tree.o print-tree.o \ |
5 | root-tree.o dir-item.o hash.o file-item.o inode-item.o | 5 | root-tree.o dir-item.o hash.o file-item.o inode-item.o |
@@ -14,7 +14,7 @@ check=sparse $(CHECKFLAGS) | |||
14 | $(check) $< | 14 | $(check) $< |
15 | $(CC) $(CFLAGS) -c $< | 15 | $(CC) $(CFLAGS) -c $< |
16 | 16 | ||
17 | all: tester debug-tree quick-test dir-test | 17 | all: tester debug-tree quick-test dir-test tags |
18 | 18 | ||
19 | debug-tree: $(objects) debug-tree.o | 19 | debug-tree: $(objects) debug-tree.o |
20 | gcc $(CFLAGS) -o debug-tree $(objects) debug-tree.o | 20 | gcc $(CFLAGS) -o debug-tree $(objects) debug-tree.o |
diff --git a/fs/btrfs/TODO b/fs/btrfs/TODO index 2ae4b3aae1e5..e9894999322e 100644 --- a/fs/btrfs/TODO +++ b/fs/btrfs/TODO | |||
@@ -8,6 +8,8 @@ | |||
8 | * Add block mapping tree (simple dm layer) | 8 | * Add block mapping tree (simple dm layer) |
9 | * Add simple tree locking (semaphore per tree) | 9 | * Add simple tree locking (semaphore per tree) |
10 | * Make allocator smarter | 10 | * Make allocator smarter |
11 | * Only pin blocks allocated in this transaction | ||
12 | * Add transaction handles | ||
11 | * Do actual block accounting | 13 | * Do actual block accounting |
12 | * Check compat and incompat flags on the inode | 14 | * Check compat and incompat flags on the inode |
13 | * Port into the kernel | 15 | * Port into the kernel |
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 13128b5ed65c..17a3ff2f1828 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
@@ -6,17 +6,18 @@ | |||
6 | #include "disk-io.h" | 6 | #include "disk-io.h" |
7 | #include "print-tree.h" | 7 | #include "print-tree.h" |
8 | 8 | ||
9 | static int split_node(struct btrfs_root *root, struct btrfs_path *path, | 9 | static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root |
10 | int level); | 10 | *root, struct btrfs_path *path, int level); |
11 | static int split_leaf(struct btrfs_root *root, struct btrfs_path *path, | 11 | static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root |
12 | int data_size); | 12 | *root, struct btrfs_path *path, int data_size); |
13 | static int push_node_left(struct btrfs_root *root, struct btrfs_buffer *dst, | 13 | static int push_node_left(struct btrfs_trans_handle *trans, struct btrfs_root |
14 | struct btrfs_buffer *src); | 14 | *root, struct btrfs_buffer *dst, struct btrfs_buffer |
15 | static int balance_node_right(struct btrfs_root *root, | 15 | *src); |
16 | struct btrfs_buffer *dst_buf, | 16 | static int balance_node_right(struct btrfs_trans_handle *trans, struct |
17 | btrfs_root *root, struct btrfs_buffer *dst_buf, | ||
17 | struct btrfs_buffer *src_buf); | 18 | struct btrfs_buffer *src_buf); |
18 | static int del_ptr(struct btrfs_root *root, struct btrfs_path *path, int level, | 19 | static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
19 | int slot); | 20 | struct btrfs_path *path, int level, int slot); |
20 | 21 | ||
21 | inline void btrfs_init_path(struct btrfs_path *p) | 22 | inline void btrfs_init_path(struct btrfs_path *p) |
22 | { | 23 | { |
@@ -34,11 +35,10 @@ void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p) | |||
34 | memset(p, 0, sizeof(*p)); | 35 | memset(p, 0, sizeof(*p)); |
35 | } | 36 | } |
36 | 37 | ||
37 | static int btrfs_cow_block(struct btrfs_root *root, | 38 | static int btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root |
38 | struct btrfs_buffer *buf, | 39 | *root, struct btrfs_buffer *buf, struct btrfs_buffer |
39 | struct btrfs_buffer *parent, | 40 | *parent, int parent_slot, struct btrfs_buffer |
40 | int parent_slot, | 41 | **cow_ret) |
41 | struct btrfs_buffer **cow_ret) | ||
42 | { | 42 | { |
43 | struct btrfs_buffer *cow; | 43 | struct btrfs_buffer *cow; |
44 | 44 | ||
@@ -46,22 +46,22 @@ static int btrfs_cow_block(struct btrfs_root *root, | |||
46 | *cow_ret = buf; | 46 | *cow_ret = buf; |
47 | return 0; | 47 | return 0; |
48 | } | 48 | } |
49 | cow = btrfs_alloc_free_block(root); | 49 | cow = btrfs_alloc_free_block(trans, root); |
50 | memcpy(&cow->node, &buf->node, root->blocksize); | 50 | memcpy(&cow->node, &buf->node, root->blocksize); |
51 | btrfs_set_header_blocknr(&cow->node.header, cow->blocknr); | 51 | btrfs_set_header_blocknr(&cow->node.header, cow->blocknr); |
52 | *cow_ret = cow; | 52 | *cow_ret = cow; |
53 | btrfs_inc_ref(root, buf); | 53 | btrfs_inc_ref(trans, root, buf); |
54 | if (buf == root->node) { | 54 | if (buf == root->node) { |
55 | root->node = cow; | 55 | root->node = cow; |
56 | cow->count++; | 56 | cow->count++; |
57 | if (buf != root->commit_root) | 57 | if (buf != root->commit_root) |
58 | btrfs_free_extent(root, buf->blocknr, 1, 1); | 58 | btrfs_free_extent(trans, root, buf->blocknr, 1, 1); |
59 | btrfs_block_release(root, buf); | 59 | btrfs_block_release(root, buf); |
60 | } else { | 60 | } else { |
61 | btrfs_set_node_blockptr(&parent->node, parent_slot, | 61 | btrfs_set_node_blockptr(&parent->node, parent_slot, |
62 | cow->blocknr); | 62 | cow->blocknr); |
63 | BUG_ON(list_empty(&parent->dirty)); | 63 | BUG_ON(list_empty(&parent->dirty)); |
64 | btrfs_free_extent(root, buf->blocknr, 1, 1); | 64 | btrfs_free_extent(trans, root, buf->blocknr, 1, 1); |
65 | } | 65 | } |
66 | btrfs_block_release(root, buf); | 66 | btrfs_block_release(root, buf); |
67 | return 0; | 67 | return 0; |
@@ -266,8 +266,8 @@ static struct btrfs_buffer *read_node_slot(struct btrfs_root *root, | |||
266 | return read_tree_block(root, btrfs_node_blockptr(node, slot)); | 266 | return read_tree_block(root, btrfs_node_blockptr(node, slot)); |
267 | } | 267 | } |
268 | 268 | ||
269 | static int balance_level(struct btrfs_root *root, struct btrfs_path *path, | 269 | static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root |
270 | int level) | 270 | *root, struct btrfs_path *path, int level) |
271 | { | 271 | { |
272 | struct btrfs_buffer *right_buf; | 272 | struct btrfs_buffer *right_buf; |
273 | struct btrfs_buffer *mid_buf; | 273 | struct btrfs_buffer *mid_buf; |
@@ -310,8 +310,8 @@ static int balance_level(struct btrfs_root *root, struct btrfs_path *path, | |||
310 | btrfs_block_release(root, mid_buf); | 310 | btrfs_block_release(root, mid_buf); |
311 | /* once for the root ptr */ | 311 | /* once for the root ptr */ |
312 | btrfs_block_release(root, mid_buf); | 312 | btrfs_block_release(root, mid_buf); |
313 | clean_tree_block(root, mid_buf); | 313 | clean_tree_block(trans, root, mid_buf); |
314 | return btrfs_free_extent(root, blocknr, 1, 1); | 314 | return btrfs_free_extent(trans, root, blocknr, 1, 1); |
315 | } | 315 | } |
316 | parent = &parent_buf->node; | 316 | parent = &parent_buf->node; |
317 | 317 | ||
@@ -324,11 +324,11 @@ static int balance_level(struct btrfs_root *root, struct btrfs_path *path, | |||
324 | 324 | ||
325 | /* first, try to make some room in the middle buffer */ | 325 | /* first, try to make some room in the middle buffer */ |
326 | if (left_buf) { | 326 | if (left_buf) { |
327 | btrfs_cow_block(root, left_buf, parent_buf, | 327 | btrfs_cow_block(trans, root, left_buf, parent_buf, pslot - 1, |
328 | pslot - 1, &left_buf); | 328 | &left_buf); |
329 | left = &left_buf->node; | 329 | left = &left_buf->node; |
330 | orig_slot += btrfs_header_nritems(&left->header); | 330 | orig_slot += btrfs_header_nritems(&left->header); |
331 | wret = push_node_left(root, left_buf, mid_buf); | 331 | wret = push_node_left(trans, root, left_buf, mid_buf); |
332 | if (wret < 0) | 332 | if (wret < 0) |
333 | ret = wret; | 333 | ret = wret; |
334 | } | 334 | } |
@@ -337,22 +337,23 @@ static int balance_level(struct btrfs_root *root, struct btrfs_path *path, | |||
337 | * then try to empty the right most buffer into the middle | 337 | * then try to empty the right most buffer into the middle |
338 | */ | 338 | */ |
339 | if (right_buf) { | 339 | if (right_buf) { |
340 | btrfs_cow_block(root, right_buf, parent_buf, | 340 | btrfs_cow_block(trans, root, right_buf, parent_buf, pslot + 1, |
341 | pslot + 1, &right_buf); | 341 | &right_buf); |
342 | right = &right_buf->node; | 342 | right = &right_buf->node; |
343 | wret = push_node_left(root, mid_buf, right_buf); | 343 | wret = push_node_left(trans, root, mid_buf, right_buf); |
344 | if (wret < 0) | 344 | if (wret < 0) |
345 | ret = wret; | 345 | ret = wret; |
346 | if (btrfs_header_nritems(&right->header) == 0) { | 346 | if (btrfs_header_nritems(&right->header) == 0) { |
347 | u64 blocknr = right_buf->blocknr; | 347 | u64 blocknr = right_buf->blocknr; |
348 | btrfs_block_release(root, right_buf); | 348 | btrfs_block_release(root, right_buf); |
349 | clean_tree_block(root, right_buf); | 349 | clean_tree_block(trans, root, right_buf); |
350 | right_buf = NULL; | 350 | right_buf = NULL; |
351 | right = NULL; | 351 | right = NULL; |
352 | wret = del_ptr(root, path, level + 1, pslot + 1); | 352 | wret = del_ptr(trans, root, path, level + 1, pslot + |
353 | 1); | ||
353 | if (wret) | 354 | if (wret) |
354 | ret = wret; | 355 | ret = wret; |
355 | wret = btrfs_free_extent(root, blocknr, 1, 1); | 356 | wret = btrfs_free_extent(trans, root, blocknr, 1, 1); |
356 | if (wret) | 357 | if (wret) |
357 | ret = wret; | 358 | ret = wret; |
358 | } else { | 359 | } else { |
@@ -373,7 +374,7 @@ static int balance_level(struct btrfs_root *root, struct btrfs_path *path, | |||
373 | * right | 374 | * right |
374 | */ | 375 | */ |
375 | BUG_ON(!left_buf); | 376 | BUG_ON(!left_buf); |
376 | wret = balance_node_right(root, mid_buf, left_buf); | 377 | wret = balance_node_right(trans, root, mid_buf, left_buf); |
377 | if (wret < 0) | 378 | if (wret < 0) |
378 | ret = wret; | 379 | ret = wret; |
379 | BUG_ON(wret == 1); | 380 | BUG_ON(wret == 1); |
@@ -382,13 +383,13 @@ static int balance_level(struct btrfs_root *root, struct btrfs_path *path, | |||
382 | /* we've managed to empty the middle node, drop it */ | 383 | /* we've managed to empty the middle node, drop it */ |
383 | u64 blocknr = mid_buf->blocknr; | 384 | u64 blocknr = mid_buf->blocknr; |
384 | btrfs_block_release(root, mid_buf); | 385 | btrfs_block_release(root, mid_buf); |
385 | clean_tree_block(root, mid_buf); | 386 | clean_tree_block(trans, root, mid_buf); |
386 | mid_buf = NULL; | 387 | mid_buf = NULL; |
387 | mid = NULL; | 388 | mid = NULL; |
388 | wret = del_ptr(root, path, level + 1, pslot); | 389 | wret = del_ptr(trans, root, path, level + 1, pslot); |
389 | if (wret) | 390 | if (wret) |
390 | ret = wret; | 391 | ret = wret; |
391 | wret = btrfs_free_extent(root, blocknr, 1, 1); | 392 | wret = btrfs_free_extent(trans, root, blocknr, 1, 1); |
392 | if (wret) | 393 | if (wret) |
393 | ret = wret; | 394 | ret = wret; |
394 | } else { | 395 | } else { |
@@ -438,8 +439,9 @@ static int balance_level(struct btrfs_root *root, struct btrfs_path *path, | |||
438 | * tree. if ins_len < 0, nodes will be merged as we walk down the tree (if | 439 | * tree. if ins_len < 0, nodes will be merged as we walk down the tree (if |
439 | * possible) | 440 | * possible) |
440 | */ | 441 | */ |
441 | int btrfs_search_slot(struct btrfs_root *root, struct btrfs_key *key, | 442 | int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root |
442 | struct btrfs_path *p, int ins_len, int cow) | 443 | *root, struct btrfs_key *key, struct btrfs_path *p, int |
444 | ins_len, int cow) | ||
443 | { | 445 | { |
444 | struct btrfs_buffer *b; | 446 | struct btrfs_buffer *b; |
445 | struct btrfs_buffer *cow_buf; | 447 | struct btrfs_buffer *cow_buf; |
@@ -455,8 +457,9 @@ again: | |||
455 | level = btrfs_header_level(&b->node.header); | 457 | level = btrfs_header_level(&b->node.header); |
456 | if (cow) { | 458 | if (cow) { |
457 | int wret; | 459 | int wret; |
458 | wret = btrfs_cow_block(root, b, p->nodes[level + 1], | 460 | wret = btrfs_cow_block(trans, root, b, p->nodes[level + |
459 | p->slots[level + 1], &cow_buf); | 461 | 1], p->slots[level + 1], |
462 | &cow_buf); | ||
460 | b = cow_buf; | 463 | b = cow_buf; |
461 | } | 464 | } |
462 | BUG_ON(!cow && ins_len); | 465 | BUG_ON(!cow && ins_len); |
@@ -472,7 +475,7 @@ again: | |||
472 | p->slots[level] = slot; | 475 | p->slots[level] = slot; |
473 | if (ins_len > 0 && btrfs_header_nritems(&c->header) == | 476 | if (ins_len > 0 && btrfs_header_nritems(&c->header) == |
474 | BTRFS_NODEPTRS_PER_BLOCK(root)) { | 477 | BTRFS_NODEPTRS_PER_BLOCK(root)) { |
475 | int sret = split_node(root, p, level); | 478 | int sret = split_node(trans, root, p, level); |
476 | BUG_ON(sret > 0); | 479 | BUG_ON(sret > 0); |
477 | if (sret) | 480 | if (sret) |
478 | return sret; | 481 | return sret; |
@@ -480,7 +483,8 @@ again: | |||
480 | c = &b->node; | 483 | c = &b->node; |
481 | slot = p->slots[level]; | 484 | slot = p->slots[level]; |
482 | } else if (ins_len < 0) { | 485 | } else if (ins_len < 0) { |
483 | int sret = balance_level(root, p, level); | 486 | int sret = balance_level(trans, root, p, |
487 | level); | ||
484 | if (sret) | 488 | if (sret) |
485 | return sret; | 489 | return sret; |
486 | b = p->nodes[level]; | 490 | b = p->nodes[level]; |
@@ -496,7 +500,7 @@ again: | |||
496 | p->slots[level] = slot; | 500 | p->slots[level] = slot; |
497 | if (ins_len > 0 && btrfs_leaf_free_space(root, l) < | 501 | if (ins_len > 0 && btrfs_leaf_free_space(root, l) < |
498 | sizeof(struct btrfs_item) + ins_len) { | 502 | sizeof(struct btrfs_item) + ins_len) { |
499 | int sret = split_leaf(root, p, ins_len); | 503 | int sret = split_leaf(trans, root, p, ins_len); |
500 | BUG_ON(sret > 0); | 504 | BUG_ON(sret > 0); |
501 | if (sret) | 505 | if (sret) |
502 | return sret; | 506 | return sret; |
@@ -519,9 +523,9 @@ again: | |||
519 | * If this fails to write a tree block, it returns -1, but continues | 523 | * If this fails to write a tree block, it returns -1, but continues |
520 | * fixing up the blocks in ram so the tree is consistent. | 524 | * fixing up the blocks in ram so the tree is consistent. |
521 | */ | 525 | */ |
522 | static int fixup_low_keys(struct btrfs_root *root, | 526 | static int fixup_low_keys(struct btrfs_trans_handle *trans, struct btrfs_root |
523 | struct btrfs_path *path, struct btrfs_disk_key *key, | 527 | *root, struct btrfs_path *path, struct btrfs_disk_key |
524 | int level) | 528 | *key, int level) |
525 | { | 529 | { |
526 | int i; | 530 | int i; |
527 | int ret = 0; | 531 | int ret = 0; |
@@ -546,8 +550,9 @@ static int fixup_low_keys(struct btrfs_root *root, | |||
546 | * returns 0 if some ptrs were pushed left, < 0 if there was some horrible | 550 | * returns 0 if some ptrs were pushed left, < 0 if there was some horrible |
547 | * error, and > 0 if there was no room in the left hand block. | 551 | * error, and > 0 if there was no room in the left hand block. |
548 | */ | 552 | */ |
549 | static int push_node_left(struct btrfs_root *root, struct btrfs_buffer *dst_buf, | 553 | static int push_node_left(struct btrfs_trans_handle *trans, struct btrfs_root |
550 | struct btrfs_buffer *src_buf) | 554 | *root, struct btrfs_buffer *dst_buf, struct |
555 | btrfs_buffer *src_buf) | ||
551 | { | 556 | { |
552 | struct btrfs_node *src = &src_buf->node; | 557 | struct btrfs_node *src = &src_buf->node; |
553 | struct btrfs_node *dst = &dst_buf->node; | 558 | struct btrfs_node *dst = &dst_buf->node; |
@@ -589,8 +594,8 @@ static int push_node_left(struct btrfs_root *root, struct btrfs_buffer *dst_buf, | |||
589 | * | 594 | * |
590 | * this will only push up to 1/2 the contents of the left node over | 595 | * this will only push up to 1/2 the contents of the left node over |
591 | */ | 596 | */ |
592 | static int balance_node_right(struct btrfs_root *root, | 597 | static int balance_node_right(struct btrfs_trans_handle *trans, struct |
593 | struct btrfs_buffer *dst_buf, | 598 | btrfs_root *root, struct btrfs_buffer *dst_buf, |
594 | struct btrfs_buffer *src_buf) | 599 | struct btrfs_buffer *src_buf) |
595 | { | 600 | { |
596 | struct btrfs_node *src = &src_buf->node; | 601 | struct btrfs_node *src = &src_buf->node; |
@@ -635,8 +640,8 @@ static int balance_node_right(struct btrfs_root *root, | |||
635 | * | 640 | * |
636 | * returns zero on success or < 0 on failure. | 641 | * returns zero on success or < 0 on failure. |
637 | */ | 642 | */ |
638 | static int insert_new_root(struct btrfs_root *root, | 643 | static int insert_new_root(struct btrfs_trans_handle *trans, struct btrfs_root |
639 | struct btrfs_path *path, int level) | 644 | *root, struct btrfs_path *path, int level) |
640 | { | 645 | { |
641 | struct btrfs_buffer *t; | 646 | struct btrfs_buffer *t; |
642 | struct btrfs_node *lower; | 647 | struct btrfs_node *lower; |
@@ -646,7 +651,7 @@ static int insert_new_root(struct btrfs_root *root, | |||
646 | BUG_ON(path->nodes[level]); | 651 | BUG_ON(path->nodes[level]); |
647 | BUG_ON(path->nodes[level-1] != root->node); | 652 | BUG_ON(path->nodes[level-1] != root->node); |
648 | 653 | ||
649 | t = btrfs_alloc_free_block(root); | 654 | t = btrfs_alloc_free_block(trans, root); |
650 | c = &t->node; | 655 | c = &t->node; |
651 | memset(c, 0, root->blocksize); | 656 | memset(c, 0, root->blocksize); |
652 | btrfs_set_header_nritems(&c->header, 1); | 657 | btrfs_set_header_nritems(&c->header, 1); |
@@ -679,9 +684,9 @@ static int insert_new_root(struct btrfs_root *root, | |||
679 | * | 684 | * |
680 | * returns zero on success and < 0 on any error | 685 | * returns zero on success and < 0 on any error |
681 | */ | 686 | */ |
682 | static int insert_ptr(struct btrfs_root *root, | 687 | static int insert_ptr(struct btrfs_trans_handle *trans, struct btrfs_root |
683 | struct btrfs_path *path, struct btrfs_disk_key *key, | 688 | *root, struct btrfs_path *path, struct btrfs_disk_key |
684 | u64 blocknr, int slot, int level) | 689 | *key, u64 blocknr, int slot, int level) |
685 | { | 690 | { |
686 | struct btrfs_node *lower; | 691 | struct btrfs_node *lower; |
687 | int nritems; | 692 | int nritems; |
@@ -713,8 +718,8 @@ static int insert_ptr(struct btrfs_root *root, | |||
713 | * | 718 | * |
714 | * returns 0 on success and < 0 on failure | 719 | * returns 0 on success and < 0 on failure |
715 | */ | 720 | */ |
716 | static int split_node(struct btrfs_root *root, struct btrfs_path *path, | 721 | static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root |
717 | int level) | 722 | *root, struct btrfs_path *path, int level) |
718 | { | 723 | { |
719 | struct btrfs_buffer *t; | 724 | struct btrfs_buffer *t; |
720 | struct btrfs_node *c; | 725 | struct btrfs_node *c; |
@@ -729,12 +734,12 @@ static int split_node(struct btrfs_root *root, struct btrfs_path *path, | |||
729 | c = &t->node; | 734 | c = &t->node; |
730 | if (t == root->node) { | 735 | if (t == root->node) { |
731 | /* trying to split the root, lets make a new one */ | 736 | /* trying to split the root, lets make a new one */ |
732 | ret = insert_new_root(root, path, level + 1); | 737 | ret = insert_new_root(trans, root, path, level + 1); |
733 | if (ret) | 738 | if (ret) |
734 | return ret; | 739 | return ret; |
735 | } | 740 | } |
736 | c_nritems = btrfs_header_nritems(&c->header); | 741 | c_nritems = btrfs_header_nritems(&c->header); |
737 | split_buffer = btrfs_alloc_free_block(root); | 742 | split_buffer = btrfs_alloc_free_block(trans, root); |
738 | split = &split_buffer->node; | 743 | split = &split_buffer->node; |
739 | btrfs_set_header_flags(&split->header, btrfs_header_flags(&c->header)); | 744 | btrfs_set_header_flags(&split->header, btrfs_header_flags(&c->header)); |
740 | btrfs_set_header_blocknr(&split->header, split_buffer->blocknr); | 745 | btrfs_set_header_blocknr(&split->header, split_buffer->blocknr); |
@@ -748,7 +753,7 @@ static int split_node(struct btrfs_root *root, struct btrfs_path *path, | |||
748 | ret = 0; | 753 | ret = 0; |
749 | 754 | ||
750 | BUG_ON(list_empty(&t->dirty)); | 755 | BUG_ON(list_empty(&t->dirty)); |
751 | wret = insert_ptr(root, path, &split->ptrs[0].key, | 756 | wret = insert_ptr(trans, root, path, &split->ptrs[0].key, |
752 | split_buffer->blocknr, path->slots[level + 1] + 1, | 757 | split_buffer->blocknr, path->slots[level + 1] + 1, |
753 | level + 1); | 758 | level + 1); |
754 | if (wret) | 759 | if (wret) |
@@ -790,8 +795,8 @@ static int leaf_space_used(struct btrfs_leaf *l, int start, int nr) | |||
790 | * returns 1 if the push failed because the other node didn't have enough | 795 | * returns 1 if the push failed because the other node didn't have enough |
791 | * room, 0 if everything worked out and < 0 if there were major errors. | 796 | * room, 0 if everything worked out and < 0 if there were major errors. |
792 | */ | 797 | */ |
793 | static int push_leaf_right(struct btrfs_root *root, struct btrfs_path *path, | 798 | static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root |
794 | int data_size) | 799 | *root, struct btrfs_path *path, int data_size) |
795 | { | 800 | { |
796 | struct btrfs_buffer *left_buf = path->nodes[0]; | 801 | struct btrfs_buffer *left_buf = path->nodes[0]; |
797 | struct btrfs_leaf *left = &left_buf->leaf; | 802 | struct btrfs_leaf *left = &left_buf->leaf; |
@@ -824,7 +829,7 @@ static int push_leaf_right(struct btrfs_root *root, struct btrfs_path *path, | |||
824 | return 1; | 829 | return 1; |
825 | } | 830 | } |
826 | /* cow and double check */ | 831 | /* cow and double check */ |
827 | btrfs_cow_block(root, right_buf, upper, slot + 1, &right_buf); | 832 | btrfs_cow_block(trans, root, right_buf, upper, slot + 1, &right_buf); |
828 | right = &right_buf->leaf; | 833 | right = &right_buf->leaf; |
829 | free_space = btrfs_leaf_free_space(root, right); | 834 | free_space = btrfs_leaf_free_space(root, right); |
830 | if (free_space < data_size + sizeof(struct btrfs_item)) { | 835 | if (free_space < data_size + sizeof(struct btrfs_item)) { |
@@ -897,8 +902,8 @@ static int push_leaf_right(struct btrfs_root *root, struct btrfs_path *path, | |||
897 | * push some data in the path leaf to the left, trying to free up at | 902 | * push some data in the path leaf to the left, trying to free up at |
898 | * least data_size bytes. returns zero if the push worked, nonzero otherwise | 903 | * least data_size bytes. returns zero if the push worked, nonzero otherwise |
899 | */ | 904 | */ |
900 | static int push_leaf_left(struct btrfs_root *root, struct btrfs_path *path, | 905 | static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root |
901 | int data_size) | 906 | *root, struct btrfs_path *path, int data_size) |
902 | { | 907 | { |
903 | struct btrfs_buffer *right_buf = path->nodes[0]; | 908 | struct btrfs_buffer *right_buf = path->nodes[0]; |
904 | struct btrfs_leaf *right = &right_buf->leaf; | 909 | struct btrfs_leaf *right = &right_buf->leaf; |
@@ -931,7 +936,7 @@ static int push_leaf_left(struct btrfs_root *root, struct btrfs_path *path, | |||
931 | } | 936 | } |
932 | 937 | ||
933 | /* cow and double check */ | 938 | /* cow and double check */ |
934 | btrfs_cow_block(root, t, path->nodes[1], slot - 1, &t); | 939 | btrfs_cow_block(trans, root, t, path->nodes[1], slot - 1, &t); |
935 | left = &t->leaf; | 940 | left = &t->leaf; |
936 | free_space = btrfs_leaf_free_space(root, left); | 941 | free_space = btrfs_leaf_free_space(root, left); |
937 | if (free_space < data_size + sizeof(struct btrfs_item)) { | 942 | if (free_space < data_size + sizeof(struct btrfs_item)) { |
@@ -997,7 +1002,7 @@ static int push_leaf_left(struct btrfs_root *root, struct btrfs_path *path, | |||
997 | BUG_ON(list_empty(&t->dirty)); | 1002 | BUG_ON(list_empty(&t->dirty)); |
998 | BUG_ON(list_empty(&right_buf->dirty)); | 1003 | BUG_ON(list_empty(&right_buf->dirty)); |
999 | 1004 | ||
1000 | wret = fixup_low_keys(root, path, &right->items[0].key, 1); | 1005 | wret = fixup_low_keys(trans, root, path, &right->items[0].key, 1); |
1001 | if (wret) | 1006 | if (wret) |
1002 | ret = wret; | 1007 | ret = wret; |
1003 | 1008 | ||
@@ -1021,8 +1026,8 @@ static int push_leaf_left(struct btrfs_root *root, struct btrfs_path *path, | |||
1021 | * | 1026 | * |
1022 | * returns 0 if all went well and < 0 on failure. | 1027 | * returns 0 if all went well and < 0 on failure. |
1023 | */ | 1028 | */ |
1024 | static int split_leaf(struct btrfs_root *root, struct btrfs_path *path, | 1029 | static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root |
1025 | int data_size) | 1030 | *root, struct btrfs_path *path, int data_size) |
1026 | { | 1031 | { |
1027 | struct btrfs_buffer *l_buf; | 1032 | struct btrfs_buffer *l_buf; |
1028 | struct btrfs_leaf *l; | 1033 | struct btrfs_leaf *l; |
@@ -1038,11 +1043,11 @@ static int split_leaf(struct btrfs_root *root, struct btrfs_path *path, | |||
1038 | int ret; | 1043 | int ret; |
1039 | int wret; | 1044 | int wret; |
1040 | 1045 | ||
1041 | wret = push_leaf_left(root, path, data_size); | 1046 | wret = push_leaf_left(trans, root, path, data_size); |
1042 | if (wret < 0) | 1047 | if (wret < 0) |
1043 | return wret; | 1048 | return wret; |
1044 | if (wret) { | 1049 | if (wret) { |
1045 | wret = push_leaf_right(root, path, data_size); | 1050 | wret = push_leaf_right(trans, root, path, data_size); |
1046 | if (wret < 0) | 1051 | if (wret < 0) |
1047 | return wret; | 1052 | return wret; |
1048 | } | 1053 | } |
@@ -1055,14 +1060,14 @@ static int split_leaf(struct btrfs_root *root, struct btrfs_path *path, | |||
1055 | return 0; | 1060 | return 0; |
1056 | 1061 | ||
1057 | if (!path->nodes[1]) { | 1062 | if (!path->nodes[1]) { |
1058 | ret = insert_new_root(root, path, 1); | 1063 | ret = insert_new_root(trans, root, path, 1); |
1059 | if (ret) | 1064 | if (ret) |
1060 | return ret; | 1065 | return ret; |
1061 | } | 1066 | } |
1062 | slot = path->slots[0]; | 1067 | slot = path->slots[0]; |
1063 | nritems = btrfs_header_nritems(&l->header); | 1068 | nritems = btrfs_header_nritems(&l->header); |
1064 | mid = (nritems + 1)/ 2; | 1069 | mid = (nritems + 1)/ 2; |
1065 | right_buffer = btrfs_alloc_free_block(root); | 1070 | right_buffer = btrfs_alloc_free_block(trans, root); |
1066 | BUG_ON(!right_buffer); | 1071 | BUG_ON(!right_buffer); |
1067 | BUG_ON(mid == nritems); | 1072 | BUG_ON(mid == nritems); |
1068 | right = &right_buffer->leaf; | 1073 | right = &right_buffer->leaf; |
@@ -1100,7 +1105,7 @@ static int split_leaf(struct btrfs_root *root, struct btrfs_path *path, | |||
1100 | 1105 | ||
1101 | btrfs_set_header_nritems(&l->header, mid); | 1106 | btrfs_set_header_nritems(&l->header, mid); |
1102 | ret = 0; | 1107 | ret = 0; |
1103 | wret = insert_ptr(root, path, &right->items[0].key, | 1108 | wret = insert_ptr(trans, root, path, &right->items[0].key, |
1104 | right_buffer->blocknr, path->slots[1] + 1, 1); | 1109 | right_buffer->blocknr, path->slots[1] + 1, 1); |
1105 | if (wret) | 1110 | if (wret) |
1106 | ret = wret; | 1111 | ret = wret; |
@@ -1122,8 +1127,9 @@ static int split_leaf(struct btrfs_root *root, struct btrfs_path *path, | |||
1122 | * Given a key and some data, insert an item into the tree. | 1127 | * Given a key and some data, insert an item into the tree. |
1123 | * This does all the path init required, making room in the tree if needed. | 1128 | * This does all the path init required, making room in the tree if needed. |
1124 | */ | 1129 | */ |
1125 | int btrfs_insert_empty_item(struct btrfs_root *root, struct btrfs_path *path, | 1130 | int btrfs_insert_empty_item(struct btrfs_trans_handle *trans, struct btrfs_root |
1126 | struct btrfs_key *cpu_key, u32 data_size) | 1131 | *root, struct btrfs_path *path, struct btrfs_key |
1132 | *cpu_key, u32 data_size) | ||
1127 | { | 1133 | { |
1128 | int ret = 0; | 1134 | int ret = 0; |
1129 | int slot; | 1135 | int slot; |
@@ -1139,7 +1145,7 @@ int btrfs_insert_empty_item(struct btrfs_root *root, struct btrfs_path *path, | |||
1139 | /* create a root if there isn't one */ | 1145 | /* create a root if there isn't one */ |
1140 | if (!root->node) | 1146 | if (!root->node) |
1141 | BUG(); | 1147 | BUG(); |
1142 | ret = btrfs_search_slot(root, cpu_key, path, data_size, 1); | 1148 | ret = btrfs_search_slot(trans, root, cpu_key, path, data_size, 1); |
1143 | if (ret == 0) { | 1149 | if (ret == 0) { |
1144 | btrfs_release_path(root, path); | 1150 | btrfs_release_path(root, path); |
1145 | return -EEXIST; | 1151 | return -EEXIST; |
@@ -1193,7 +1199,7 @@ int btrfs_insert_empty_item(struct btrfs_root *root, struct btrfs_path *path, | |||
1193 | 1199 | ||
1194 | ret = 0; | 1200 | ret = 0; |
1195 | if (slot == 0) | 1201 | if (slot == 0) |
1196 | ret = fixup_low_keys(root, path, &disk_key, 1); | 1202 | ret = fixup_low_keys(trans, root, path, &disk_key, 1); |
1197 | 1203 | ||
1198 | BUG_ON(list_empty(&leaf_buf->dirty)); | 1204 | BUG_ON(list_empty(&leaf_buf->dirty)); |
1199 | if (btrfs_leaf_free_space(root, leaf) < 0) | 1205 | if (btrfs_leaf_free_space(root, leaf) < 0) |
@@ -1207,15 +1213,16 @@ out: | |||
1207 | * Given a key and some data, insert an item into the tree. | 1213 | * Given a key and some data, insert an item into the tree. |
1208 | * This does all the path init required, making room in the tree if needed. | 1214 | * This does all the path init required, making room in the tree if needed. |
1209 | */ | 1215 | */ |
1210 | int btrfs_insert_item(struct btrfs_root *root, struct btrfs_key *cpu_key, | 1216 | int btrfs_insert_item(struct btrfs_trans_handle *trans, struct btrfs_root |
1211 | void *data, u32 data_size) | 1217 | *root, struct btrfs_key *cpu_key, void *data, u32 |
1218 | data_size) | ||
1212 | { | 1219 | { |
1213 | int ret = 0; | 1220 | int ret = 0; |
1214 | struct btrfs_path path; | 1221 | struct btrfs_path path; |
1215 | u8 *ptr; | 1222 | u8 *ptr; |
1216 | 1223 | ||
1217 | btrfs_init_path(&path); | 1224 | btrfs_init_path(&path); |
1218 | ret = btrfs_insert_empty_item(root, &path, cpu_key, data_size); | 1225 | ret = btrfs_insert_empty_item(trans, root, &path, cpu_key, data_size); |
1219 | if (!ret) { | 1226 | if (!ret) { |
1220 | ptr = btrfs_item_ptr(&path.nodes[0]->leaf, path.slots[0], u8); | 1227 | ptr = btrfs_item_ptr(&path.nodes[0]->leaf, path.slots[0], u8); |
1221 | memcpy(ptr, data, data_size); | 1228 | memcpy(ptr, data, data_size); |
@@ -1231,8 +1238,8 @@ int btrfs_insert_item(struct btrfs_root *root, struct btrfs_key *cpu_key, | |||
1231 | * continuing all the way the root if required. The root is converted into | 1238 | * continuing all the way the root if required. The root is converted into |
1232 | * a leaf if all the nodes are emptied. | 1239 | * a leaf if all the nodes are emptied. |
1233 | */ | 1240 | */ |
1234 | static int del_ptr(struct btrfs_root *root, struct btrfs_path *path, int level, | 1241 | static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
1235 | int slot) | 1242 | struct btrfs_path *path, int level, int slot) |
1236 | { | 1243 | { |
1237 | struct btrfs_node *node; | 1244 | struct btrfs_node *node; |
1238 | struct btrfs_buffer *parent = path->nodes[level]; | 1245 | struct btrfs_buffer *parent = path->nodes[level]; |
@@ -1253,7 +1260,7 @@ static int del_ptr(struct btrfs_root *root, struct btrfs_path *path, int level, | |||
1253 | /* just turn the root into a leaf and break */ | 1260 | /* just turn the root into a leaf and break */ |
1254 | btrfs_set_header_level(&root->node->node.header, 0); | 1261 | btrfs_set_header_level(&root->node->node.header, 0); |
1255 | } else if (slot == 0) { | 1262 | } else if (slot == 0) { |
1256 | wret = fixup_low_keys(root, path, &node->ptrs[0].key, | 1263 | wret = fixup_low_keys(trans, root, path, &node->ptrs[0].key, |
1257 | level + 1); | 1264 | level + 1); |
1258 | if (wret) | 1265 | if (wret) |
1259 | ret = wret; | 1266 | ret = wret; |
@@ -1266,7 +1273,8 @@ static int del_ptr(struct btrfs_root *root, struct btrfs_path *path, int level, | |||
1266 | * delete the item at the leaf level in path. If that empties | 1273 | * delete the item at the leaf level in path. If that empties |
1267 | * the leaf, remove it from the tree | 1274 | * the leaf, remove it from the tree |
1268 | */ | 1275 | */ |
1269 | int btrfs_del_item(struct btrfs_root *root, struct btrfs_path *path) | 1276 | int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
1277 | struct btrfs_path *path) | ||
1270 | { | 1278 | { |
1271 | int slot; | 1279 | int slot; |
1272 | struct btrfs_leaf *leaf; | 1280 | struct btrfs_leaf *leaf; |
@@ -1306,19 +1314,20 @@ int btrfs_del_item(struct btrfs_root *root, struct btrfs_path *path) | |||
1306 | btrfs_set_header_level(&leaf->header, 0); | 1314 | btrfs_set_header_level(&leaf->header, 0); |
1307 | BUG_ON(list_empty(&leaf_buf->dirty)); | 1315 | BUG_ON(list_empty(&leaf_buf->dirty)); |
1308 | } else { | 1316 | } else { |
1309 | clean_tree_block(root, leaf_buf); | 1317 | clean_tree_block(trans, root, leaf_buf); |
1310 | wret = del_ptr(root, path, 1, path->slots[1]); | 1318 | wret = del_ptr(trans, root, path, 1, path->slots[1]); |
1311 | if (wret) | 1319 | if (wret) |
1312 | ret = wret; | 1320 | ret = wret; |
1313 | wret = btrfs_free_extent(root, leaf_buf->blocknr, 1, 1); | 1321 | wret = btrfs_free_extent(trans, root, |
1322 | leaf_buf->blocknr, 1, 1); | ||
1314 | if (wret) | 1323 | if (wret) |
1315 | ret = wret; | 1324 | ret = wret; |
1316 | } | 1325 | } |
1317 | } else { | 1326 | } else { |
1318 | int used = leaf_space_used(leaf, 0, nritems); | 1327 | int used = leaf_space_used(leaf, 0, nritems); |
1319 | if (slot == 0) { | 1328 | if (slot == 0) { |
1320 | wret = fixup_low_keys(root, path, | 1329 | wret = fixup_low_keys(trans, root, path, |
1321 | &leaf->items[0].key, 1); | 1330 | &leaf->items[0].key, 1); |
1322 | if (wret) | 1331 | if (wret) |
1323 | ret = wret; | 1332 | ret = wret; |
1324 | } | 1333 | } |
@@ -1332,23 +1341,24 @@ int btrfs_del_item(struct btrfs_root *root, struct btrfs_path *path) | |||
1332 | */ | 1341 | */ |
1333 | slot = path->slots[1]; | 1342 | slot = path->slots[1]; |
1334 | leaf_buf->count++; | 1343 | leaf_buf->count++; |
1335 | wret = push_leaf_left(root, path, 1); | 1344 | wret = push_leaf_left(trans, root, path, 1); |
1336 | if (wret < 0) | 1345 | if (wret < 0) |
1337 | ret = wret; | 1346 | ret = wret; |
1338 | if (path->nodes[0] == leaf_buf && | 1347 | if (path->nodes[0] == leaf_buf && |
1339 | btrfs_header_nritems(&leaf->header)) { | 1348 | btrfs_header_nritems(&leaf->header)) { |
1340 | wret = push_leaf_right(root, path, 1); | 1349 | wret = push_leaf_right(trans, root, path, 1); |
1341 | if (wret < 0) | 1350 | if (wret < 0) |
1342 | ret = wret; | 1351 | ret = wret; |
1343 | } | 1352 | } |
1344 | if (btrfs_header_nritems(&leaf->header) == 0) { | 1353 | if (btrfs_header_nritems(&leaf->header) == 0) { |
1345 | u64 blocknr = leaf_buf->blocknr; | 1354 | u64 blocknr = leaf_buf->blocknr; |
1346 | clean_tree_block(root, leaf_buf); | 1355 | clean_tree_block(trans, root, leaf_buf); |
1347 | wret = del_ptr(root, path, 1, slot); | 1356 | wret = del_ptr(trans, root, path, 1, slot); |
1348 | if (wret) | 1357 | if (wret) |
1349 | ret = wret; | 1358 | ret = wret; |
1350 | btrfs_block_release(root, leaf_buf); | 1359 | btrfs_block_release(root, leaf_buf); |
1351 | wret = btrfs_free_extent(root, blocknr, 1, 1); | 1360 | wret = btrfs_free_extent(trans, root, blocknr, |
1361 | 1, 1); | ||
1352 | if (wret) | 1362 | if (wret) |
1353 | ret = wret; | 1363 | ret = wret; |
1354 | } else { | 1364 | } else { |
@@ -1401,5 +1411,3 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path) | |||
1401 | } | 1411 | } |
1402 | return 0; | 1412 | return 0; |
1403 | } | 1413 | } |
1404 | |||
1405 | |||
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index d15a2ed95076..68f0af39777f 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -4,6 +4,8 @@ | |||
4 | #include "list.h" | 4 | #include "list.h" |
5 | #include "kerncompat.h" | 5 | #include "kerncompat.h" |
6 | 6 | ||
7 | struct btrfs_trans_handle; | ||
8 | |||
7 | #define BTRFS_MAGIC "_BtRfS_M" | 9 | #define BTRFS_MAGIC "_BtRfS_M" |
8 | 10 | ||
9 | #define BTRFS_ROOT_TREE_OBJECTID 1 | 11 | #define BTRFS_ROOT_TREE_OBJECTID 1 |
@@ -200,6 +202,7 @@ struct btrfs_root { | |||
200 | struct btrfs_root_item root_item; | 202 | struct btrfs_root_item root_item; |
201 | struct btrfs_key root_key; | 203 | struct btrfs_key root_key; |
202 | u32 blocksize; | 204 | u32 blocksize; |
205 | struct btrfs_trans_handle *running_transaction; | ||
203 | }; | 206 | }; |
204 | 207 | ||
205 | /* the lower bits in the key flags defines the item type */ | 208 | /* the lower bits in the key flags defines the item type */ |
@@ -656,34 +659,46 @@ static inline u8 *btrfs_leaf_data(struct btrfs_leaf *l) | |||
656 | ((type *)(btrfs_leaf_data(leaf) + \ | 659 | ((type *)(btrfs_leaf_data(leaf) + \ |
657 | btrfs_item_offset((leaf)->items + (slot)))) | 660 | btrfs_item_offset((leaf)->items + (slot)))) |
658 | 661 | ||
659 | struct btrfs_buffer *btrfs_alloc_free_block(struct btrfs_root *root); | 662 | struct btrfs_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans, |
660 | int btrfs_inc_ref(struct btrfs_root *root, struct btrfs_buffer *buf); | 663 | struct btrfs_root *root); |
661 | int btrfs_free_extent(struct btrfs_root *root, u64 blocknr, u64 num_blocks, | 664 | int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
662 | int pin); | 665 | struct btrfs_buffer *buf); |
663 | int btrfs_search_slot(struct btrfs_root *root, struct btrfs_key *key, | 666 | int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root |
664 | struct btrfs_path *p, int ins_len, int cow); | 667 | *root, u64 blocknr, u64 num_blocks, int pin); |
668 | int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root | ||
669 | *root, struct btrfs_key *key, struct btrfs_path *p, int | ||
670 | ins_len, int cow); | ||
665 | void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p); | 671 | void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p); |
666 | void btrfs_init_path(struct btrfs_path *p); | 672 | void btrfs_init_path(struct btrfs_path *p); |
667 | int btrfs_del_item(struct btrfs_root *root, struct btrfs_path *path); | 673 | int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
668 | int btrfs_insert_item(struct btrfs_root *root, struct btrfs_key *key, | 674 | struct btrfs_path *path); |
669 | void *data, u32 data_size); | 675 | int btrfs_insert_item(struct btrfs_trans_handle *trans, struct btrfs_root |
670 | int btrfs_insert_empty_item(struct btrfs_root *root, struct btrfs_path *path, | 676 | *root, struct btrfs_key *key, void *data, u32 data_size); |
671 | struct btrfs_key *cpu_key, u32 data_size); | 677 | int btrfs_insert_empty_item(struct btrfs_trans_handle *trans, struct btrfs_root |
678 | *root, struct btrfs_path *path, struct btrfs_key | ||
679 | *cpu_key, u32 data_size); | ||
672 | int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path); | 680 | int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path); |
673 | int btrfs_leaf_free_space(struct btrfs_root *root, struct btrfs_leaf *leaf); | 681 | int btrfs_leaf_free_space(struct btrfs_root *root, struct btrfs_leaf *leaf); |
674 | int btrfs_drop_snapshot(struct btrfs_root *root, struct btrfs_buffer *snap); | 682 | int btrfs_drop_snapshot(struct btrfs_trans_handle *trans, struct btrfs_root |
675 | int btrfs_finish_extent_commit(struct btrfs_root *root); | 683 | *root, struct btrfs_buffer *snap); |
676 | int btrfs_del_root(struct btrfs_root *root, struct btrfs_key *key); | 684 | int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct |
677 | int btrfs_insert_root(struct btrfs_root *root, struct btrfs_key *key, | 685 | btrfs_root *root); |
678 | struct btrfs_root_item *item); | 686 | int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
679 | int btrfs_update_root(struct btrfs_root *root, struct btrfs_key *key, | 687 | struct btrfs_key *key); |
680 | struct btrfs_root_item *item); | 688 | int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root |
681 | int btrfs_find_last_root(struct btrfs_root *root, u64 objectid, | 689 | *root, struct btrfs_key *key, struct btrfs_root_item |
682 | struct btrfs_root_item *item, struct btrfs_key *key); | 690 | *item); |
683 | int btrfs_insert_dir_item(struct btrfs_root *root, char *name, int name_len, | 691 | int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root |
684 | u64 dir, u64 objectid, u8 type); | 692 | *root, struct btrfs_key *key, struct btrfs_root_item |
685 | int btrfs_lookup_dir_item(struct btrfs_root *root, struct btrfs_path *path, | 693 | *item); |
686 | u64 dir, char *name, int name_len, int mod); | 694 | int btrfs_find_last_root(struct btrfs_root *root, u64 objectid, struct |
695 | btrfs_root_item *item, struct btrfs_key *key); | ||
696 | int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root | ||
697 | *root, char *name, int name_len, u64 dir, u64 | ||
698 | objectid, u8 type); | ||
699 | int btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root | ||
700 | *root, struct btrfs_path *path, u64 dir, char *name, | ||
701 | int name_len, int mod); | ||
687 | int btrfs_match_dir_item_name(struct btrfs_root *root, struct btrfs_path *path, | 702 | int btrfs_match_dir_item_name(struct btrfs_root *root, struct btrfs_path *path, |
688 | char *name, int name_len); | 703 | char *name, int name_len); |
689 | #endif | 704 | #endif |
diff --git a/fs/btrfs/debug-tree.c b/fs/btrfs/debug-tree.c index de45fb4dfddd..91dea7a0a476 100644 --- a/fs/btrfs/debug-tree.c +++ b/fs/btrfs/debug-tree.c | |||
@@ -5,6 +5,7 @@ | |||
5 | #include "ctree.h" | 5 | #include "ctree.h" |
6 | #include "disk-io.h" | 6 | #include "disk-io.h" |
7 | #include "print-tree.h" | 7 | #include "print-tree.h" |
8 | #include "transaction.h" | ||
8 | 9 | ||
9 | int main(int ac, char **av) { | 10 | int main(int ac, char **av) { |
10 | struct btrfs_super_block super; | 11 | struct btrfs_super_block super; |
diff --git a/fs/btrfs/dir-item.c b/fs/btrfs/dir-item.c index a42a67b99753..949c4e526798 100644 --- a/fs/btrfs/dir-item.c +++ b/fs/btrfs/dir-item.c | |||
@@ -5,9 +5,11 @@ | |||
5 | #include "ctree.h" | 5 | #include "ctree.h" |
6 | #include "disk-io.h" | 6 | #include "disk-io.h" |
7 | #include "hash.h" | 7 | #include "hash.h" |
8 | #include "transaction.h" | ||
8 | 9 | ||
9 | int btrfs_insert_dir_item(struct btrfs_root *root, char *name, int name_len, | 10 | int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root |
10 | u64 dir, u64 objectid, u8 type) | 11 | *root, char *name, int name_len, u64 dir, u64 |
12 | objectid, u8 type) | ||
11 | { | 13 | { |
12 | int ret = 0; | 14 | int ret = 0; |
13 | struct btrfs_path path; | 15 | struct btrfs_path path; |
@@ -23,7 +25,7 @@ int btrfs_insert_dir_item(struct btrfs_root *root, char *name, int name_len, | |||
23 | BUG_ON(ret); | 25 | BUG_ON(ret); |
24 | btrfs_init_path(&path); | 26 | btrfs_init_path(&path); |
25 | data_size = sizeof(*dir_item) + name_len; | 27 | data_size = sizeof(*dir_item) + name_len; |
26 | ret = btrfs_insert_empty_item(root, &path, &key, data_size); | 28 | ret = btrfs_insert_empty_item(trans, root, &path, &key, data_size); |
27 | if (ret) | 29 | if (ret) |
28 | goto out; | 30 | goto out; |
29 | 31 | ||
@@ -40,8 +42,9 @@ out: | |||
40 | return ret; | 42 | return ret; |
41 | } | 43 | } |
42 | 44 | ||
43 | int btrfs_lookup_dir_item(struct btrfs_root *root, struct btrfs_path *path, | 45 | int btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root |
44 | u64 dir, char *name, int name_len, int mod) | 46 | *root, struct btrfs_path *path, u64 dir, char *name, |
47 | int name_len, int mod) | ||
45 | { | 48 | { |
46 | int ret; | 49 | int ret; |
47 | struct btrfs_key key; | 50 | struct btrfs_key key; |
@@ -53,12 +56,13 @@ int btrfs_lookup_dir_item(struct btrfs_root *root, struct btrfs_path *path, | |||
53 | btrfs_set_key_type(&key, BTRFS_DIR_ITEM_KEY); | 56 | btrfs_set_key_type(&key, BTRFS_DIR_ITEM_KEY); |
54 | ret = btrfs_name_hash(name, name_len, &key.offset); | 57 | ret = btrfs_name_hash(name, name_len, &key.offset); |
55 | BUG_ON(ret); | 58 | BUG_ON(ret); |
56 | ret = btrfs_search_slot(root, &key, path, ins_len, cow); | 59 | ret = btrfs_search_slot(trans, root, &key, path, ins_len, cow); |
57 | return ret; | 60 | return ret; |
58 | } | 61 | } |
59 | 62 | ||
60 | int btrfs_match_dir_item_name(struct btrfs_root *root, struct btrfs_path *path, | 63 | int btrfs_match_dir_item_name(struct btrfs_root *root, |
61 | char *name, int name_len) | 64 | struct btrfs_path *path, char |
65 | *name, int name_len) | ||
62 | { | 66 | { |
63 | struct btrfs_dir_item *dir_item; | 67 | struct btrfs_dir_item *dir_item; |
64 | char *name_ptr; | 68 | char *name_ptr; |
diff --git a/fs/btrfs/dir-test.c b/fs/btrfs/dir-test.c index f73aa7623398..e908c0c588cc 100644 --- a/fs/btrfs/dir-test.c +++ b/fs/btrfs/dir-test.c | |||
@@ -8,6 +8,7 @@ | |||
8 | #include "disk-io.h" | 8 | #include "disk-io.h" |
9 | #include "print-tree.h" | 9 | #include "print-tree.h" |
10 | #include "hash.h" | 10 | #include "hash.h" |
11 | #include "transaction.h" | ||
11 | 12 | ||
12 | int keep_running = 1; | 13 | int keep_running = 1; |
13 | struct btrfs_super_block super; | 14 | struct btrfs_super_block super; |
@@ -38,7 +39,8 @@ again: | |||
38 | return 0; | 39 | return 0; |
39 | } | 40 | } |
40 | 41 | ||
41 | static int ins_one(struct btrfs_root *root, struct radix_tree_root *radix) | 42 | static int ins_one(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
43 | struct radix_tree_root *radix) | ||
42 | { | 44 | { |
43 | int ret; | 45 | int ret; |
44 | char buf[128]; | 46 | char buf[128]; |
@@ -48,8 +50,8 @@ static int ins_one(struct btrfs_root *root, struct radix_tree_root *radix) | |||
48 | find_num(radix, &oid, 0); | 50 | find_num(radix, &oid, 0); |
49 | sprintf(buf, "str-%lu", oid); | 51 | sprintf(buf, "str-%lu", oid); |
50 | 52 | ||
51 | ret = btrfs_insert_dir_item(root, buf, strlen(buf), dir_oid, file_oid, | 53 | ret = btrfs_insert_dir_item(trans, root, buf, strlen(buf), dir_oid, |
52 | 1); | 54 | file_oid, 1); |
53 | if (ret) | 55 | if (ret) |
54 | goto error; | 56 | goto error; |
55 | 57 | ||
@@ -68,7 +70,8 @@ error: | |||
68 | * check | 70 | * check |
69 | */ | 71 | */ |
70 | btrfs_init_path(&path); | 72 | btrfs_init_path(&path); |
71 | ret = btrfs_lookup_dir_item(root, &path, dir_oid, buf, strlen(buf), 0); | 73 | ret = btrfs_lookup_dir_item(trans, root, &path, dir_oid, buf, |
74 | strlen(buf), 0); | ||
72 | if (ret) | 75 | if (ret) |
73 | goto fatal_release; | 76 | goto fatal_release; |
74 | if (!btrfs_match_dir_item_name(root, &path, buf, strlen(buf))) { | 77 | if (!btrfs_match_dir_item_name(root, &path, buf, strlen(buf))) { |
@@ -96,7 +99,8 @@ fatal: | |||
96 | return -1; | 99 | return -1; |
97 | } | 100 | } |
98 | 101 | ||
99 | static int insert_dup(struct btrfs_root *root, struct radix_tree_root *radix) | 102 | static int insert_dup(struct btrfs_trans_handle *trans, struct btrfs_root |
103 | *root, struct radix_tree_root *radix) | ||
100 | { | 104 | { |
101 | int ret; | 105 | int ret; |
102 | char buf[128]; | 106 | char buf[128]; |
@@ -107,8 +111,8 @@ static int insert_dup(struct btrfs_root *root, struct radix_tree_root *radix) | |||
107 | return 0; | 111 | return 0; |
108 | sprintf(buf, "str-%lu", oid); | 112 | sprintf(buf, "str-%lu", oid); |
109 | 113 | ||
110 | ret = btrfs_insert_dir_item(root, buf, strlen(buf), dir_oid, file_oid, | 114 | ret = btrfs_insert_dir_item(trans, root, buf, strlen(buf), dir_oid, |
111 | 1); | 115 | file_oid, 1); |
112 | if (ret != -EEXIST) { | 116 | if (ret != -EEXIST) { |
113 | printf("insert on %s gave us %d\n", buf, ret); | 117 | printf("insert on %s gave us %d\n", buf, ret); |
114 | return 1; | 118 | return 1; |
@@ -116,7 +120,8 @@ static int insert_dup(struct btrfs_root *root, struct radix_tree_root *radix) | |||
116 | return 0; | 120 | return 0; |
117 | } | 121 | } |
118 | 122 | ||
119 | static int del_one(struct btrfs_root *root, struct radix_tree_root *radix) | 123 | static int del_one(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
124 | struct radix_tree_root *radix) | ||
120 | { | 125 | { |
121 | int ret; | 126 | int ret; |
122 | char buf[128]; | 127 | char buf[128]; |
@@ -129,10 +134,11 @@ static int del_one(struct btrfs_root *root, struct radix_tree_root *radix) | |||
129 | return 0; | 134 | return 0; |
130 | sprintf(buf, "str-%lu", oid); | 135 | sprintf(buf, "str-%lu", oid); |
131 | btrfs_init_path(&path); | 136 | btrfs_init_path(&path); |
132 | ret = btrfs_lookup_dir_item(root, &path, dir_oid, buf, strlen(buf), -1); | 137 | ret = btrfs_lookup_dir_item(trans, root, &path, dir_oid, buf, |
138 | strlen(buf), -1); | ||
133 | if (ret) | 139 | if (ret) |
134 | goto out_release; | 140 | goto out_release; |
135 | ret = btrfs_del_item(root, &path); | 141 | ret = btrfs_del_item(trans, root, &path); |
136 | if (ret) | 142 | if (ret) |
137 | goto out_release; | 143 | goto out_release; |
138 | btrfs_release_path(root, &path); | 144 | btrfs_release_path(root, &path); |
@@ -149,7 +155,8 @@ out: | |||
149 | return -1; | 155 | return -1; |
150 | } | 156 | } |
151 | 157 | ||
152 | static int lookup_item(struct btrfs_root *root, struct radix_tree_root *radix) | 158 | static int lookup_item(struct btrfs_trans_handle *trans, struct btrfs_root |
159 | *root, struct radix_tree_root *radix) | ||
153 | { | 160 | { |
154 | struct btrfs_path path; | 161 | struct btrfs_path path; |
155 | char buf[128]; | 162 | char buf[128]; |
@@ -161,7 +168,8 @@ static int lookup_item(struct btrfs_root *root, struct radix_tree_root *radix) | |||
161 | return 0; | 168 | return 0; |
162 | sprintf(buf, "str-%lu", oid); | 169 | sprintf(buf, "str-%lu", oid); |
163 | btrfs_init_path(&path); | 170 | btrfs_init_path(&path); |
164 | ret = btrfs_lookup_dir_item(root, &path, dir_oid, buf, strlen(buf), 0); | 171 | ret = btrfs_lookup_dir_item(trans, root, &path, dir_oid, buf, |
172 | strlen(buf), 0); | ||
165 | btrfs_release_path(root, &path); | 173 | btrfs_release_path(root, &path); |
166 | if (ret) { | 174 | if (ret) { |
167 | printf("unable to find key %lu\n", oid); | 175 | printf("unable to find key %lu\n", oid); |
@@ -170,7 +178,8 @@ static int lookup_item(struct btrfs_root *root, struct radix_tree_root *radix) | |||
170 | return 0; | 178 | return 0; |
171 | } | 179 | } |
172 | 180 | ||
173 | static int lookup_enoent(struct btrfs_root *root, struct radix_tree_root *radix) | 181 | static int lookup_enoent(struct btrfs_trans_handle *trans, struct btrfs_root |
182 | *root, struct radix_tree_root *radix) | ||
174 | { | 183 | { |
175 | struct btrfs_path path; | 184 | struct btrfs_path path; |
176 | char buf[128]; | 185 | char buf[128]; |
@@ -182,7 +191,8 @@ static int lookup_enoent(struct btrfs_root *root, struct radix_tree_root *radix) | |||
182 | return 0; | 191 | return 0; |
183 | sprintf(buf, "str-%lu", oid); | 192 | sprintf(buf, "str-%lu", oid); |
184 | btrfs_init_path(&path); | 193 | btrfs_init_path(&path); |
185 | ret = btrfs_lookup_dir_item(root, &path, dir_oid, buf, strlen(buf), 0); | 194 | ret = btrfs_lookup_dir_item(trans, root, &path, dir_oid, buf, |
195 | strlen(buf), 0); | ||
186 | btrfs_release_path(root, &path); | 196 | btrfs_release_path(root, &path); |
187 | if (!ret) { | 197 | if (!ret) { |
188 | printf("able to find key that should not exist %lu\n", oid); | 198 | printf("able to find key that should not exist %lu\n", oid); |
@@ -191,8 +201,8 @@ static int lookup_enoent(struct btrfs_root *root, struct radix_tree_root *radix) | |||
191 | return 0; | 201 | return 0; |
192 | } | 202 | } |
193 | 203 | ||
194 | static int empty_tree(struct btrfs_root *root, struct radix_tree_root *radix, | 204 | static int empty_tree(struct btrfs_trans_handle *trans, struct btrfs_root |
195 | int nr) | 205 | *root, struct radix_tree_root *radix, int nr) |
196 | { | 206 | { |
197 | struct btrfs_path path; | 207 | struct btrfs_path path; |
198 | struct btrfs_key key; | 208 | struct btrfs_key key; |
@@ -211,7 +221,7 @@ static int empty_tree(struct btrfs_root *root, struct radix_tree_root *radix, | |||
211 | key.objectid = dir_oid; | 221 | key.objectid = dir_oid; |
212 | while(nr-- >= 0) { | 222 | while(nr-- >= 0) { |
213 | btrfs_init_path(&path); | 223 | btrfs_init_path(&path); |
214 | ret = btrfs_search_slot(root, &key, &path, -1, 1); | 224 | ret = btrfs_search_slot(trans, root, &key, &path, -1, 1); |
215 | if (ret < 0) { | 225 | if (ret < 0) { |
216 | btrfs_release_path(root, &path); | 226 | btrfs_release_path(root, &path); |
217 | return ret; | 227 | return ret; |
@@ -231,7 +241,7 @@ static int empty_tree(struct btrfs_root *root, struct radix_tree_root *radix, | |||
231 | BUG_ON(found_len > 128); | 241 | BUG_ON(found_len > 128); |
232 | buf[found_len] = '\0'; | 242 | buf[found_len] = '\0'; |
233 | found = atoi(buf + 4); | 243 | found = atoi(buf + 4); |
234 | ret = btrfs_del_item(root, &path); | 244 | ret = btrfs_del_item(trans, root, &path); |
235 | count++; | 245 | count++; |
236 | if (ret) { | 246 | if (ret) { |
237 | fprintf(stderr, | 247 | fprintf(stderr, |
@@ -252,19 +262,19 @@ error: | |||
252 | return -1; | 262 | return -1; |
253 | } | 263 | } |
254 | 264 | ||
255 | static int fill_tree(struct btrfs_root *root, struct radix_tree_root *radix, | 265 | static int fill_tree(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
256 | int count) | 266 | struct radix_tree_root *radix, int count) |
257 | { | 267 | { |
258 | int i; | 268 | int i; |
259 | int ret = 0; | 269 | int ret = 0; |
260 | for (i = 0; i < count; i++) { | 270 | for (i = 0; i < count; i++) { |
261 | ret = ins_one(root, radix); | 271 | ret = ins_one(trans, root, radix); |
262 | if (ret) { | 272 | if (ret) { |
263 | fprintf(stderr, "fill failed\n"); | 273 | fprintf(stderr, "fill failed\n"); |
264 | goto out; | 274 | goto out; |
265 | } | 275 | } |
266 | if (i % 1000 == 0) { | 276 | if (i % 1000 == 0) { |
267 | ret = btrfs_commit_transaction(root, &super); | 277 | ret = btrfs_commit_transaction(trans, root, &super); |
268 | if (ret) { | 278 | if (ret) { |
269 | fprintf(stderr, "fill commit failed\n"); | 279 | fprintf(stderr, "fill commit failed\n"); |
270 | return ret; | 280 | return ret; |
@@ -280,7 +290,8 @@ out: | |||
280 | return ret; | 290 | return ret; |
281 | } | 291 | } |
282 | 292 | ||
283 | static int bulk_op(struct btrfs_root *root, struct radix_tree_root *radix) | 293 | static int bulk_op(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
294 | struct radix_tree_root *radix) | ||
284 | { | 295 | { |
285 | int ret; | 296 | int ret; |
286 | int nr = rand() % 5000; | 297 | int nr = rand() % 5000; |
@@ -289,17 +300,18 @@ static int bulk_op(struct btrfs_root *root, struct radix_tree_root *radix) | |||
289 | /* do the bulk op much less frequently */ | 300 | /* do the bulk op much less frequently */ |
290 | if (run_nr++ % 100) | 301 | if (run_nr++ % 100) |
291 | return 0; | 302 | return 0; |
292 | ret = empty_tree(root, radix, nr); | 303 | ret = empty_tree(trans, root, radix, nr); |
293 | if (ret) | 304 | if (ret) |
294 | return ret; | 305 | return ret; |
295 | ret = fill_tree(root, radix, nr); | 306 | ret = fill_tree(trans, root, radix, nr); |
296 | if (ret) | 307 | if (ret) |
297 | return ret; | 308 | return ret; |
298 | return 0; | 309 | return 0; |
299 | } | 310 | } |
300 | 311 | ||
301 | 312 | ||
302 | int (*ops[])(struct btrfs_root *root, struct radix_tree_root *radix) = | 313 | int (*ops[])(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct |
314 | radix_tree_root *radix) = | ||
303 | { ins_one, insert_dup, del_one, lookup_item, | 315 | { ins_one, insert_dup, del_one, lookup_item, |
304 | lookup_enoent, bulk_op }; | 316 | lookup_enoent, bulk_op }; |
305 | 317 | ||
@@ -330,11 +342,13 @@ int main(int ac, char **av) | |||
330 | int init_fill_count = 800000; | 342 | int init_fill_count = 800000; |
331 | int err = 0; | 343 | int err = 0; |
332 | int initial_only = 0; | 344 | int initial_only = 0; |
345 | struct btrfs_trans_handle *trans; | ||
333 | radix_tree_init(); | 346 | radix_tree_init(); |
334 | 347 | ||
335 | printf("removing old tree\n"); | 348 | printf("removing old tree\n"); |
336 | unlink("dbfile"); | 349 | unlink("dbfile"); |
337 | root = open_ctree("dbfile", &super); | 350 | root = open_ctree("dbfile", &super); |
351 | trans = btrfs_start_transaction(root, 1); | ||
338 | 352 | ||
339 | signal(SIGTERM, sigstopper); | 353 | signal(SIGTERM, sigstopper); |
340 | signal(SIGINT, sigstopper); | 354 | signal(SIGINT, sigstopper); |
@@ -353,7 +367,7 @@ int main(int ac, char **av) | |||
353 | } | 367 | } |
354 | } | 368 | } |
355 | printf("initial fill\n"); | 369 | printf("initial fill\n"); |
356 | ret = fill_tree(root, &radix, init_fill_count); | 370 | ret = fill_tree(trans, root, &radix, init_fill_count); |
357 | printf("starting run\n"); | 371 | printf("starting run\n"); |
358 | if (ret) { | 372 | if (ret) { |
359 | err = ret; | 373 | err = ret; |
@@ -377,7 +391,7 @@ int main(int ac, char **av) | |||
377 | root = open_ctree("dbfile", &super); | 391 | root = open_ctree("dbfile", &super); |
378 | } | 392 | } |
379 | while(count--) { | 393 | while(count--) { |
380 | ret = ops[op](root, &radix); | 394 | ret = ops[op](trans, root, &radix); |
381 | if (ret) { | 395 | if (ret) { |
382 | fprintf(stderr, "op %d failed %d:%d\n", | 396 | fprintf(stderr, "op %d failed %d:%d\n", |
383 | op, i, iterations); | 397 | op, i, iterations); |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 8d9457b5aef5..25ce07908ee3 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include "radix-tree.h" | 9 | #include "radix-tree.h" |
10 | #include "ctree.h" | 10 | #include "ctree.h" |
11 | #include "disk-io.h" | 11 | #include "disk-io.h" |
12 | #include "transaction.h" | ||
12 | 13 | ||
13 | static int allocated_blocks = 0; | 14 | static int allocated_blocks = 0; |
14 | int cache_max = 10000; | 15 | int cache_max = 10000; |
@@ -107,7 +108,8 @@ struct btrfs_buffer *read_tree_block(struct btrfs_root *root, u64 blocknr) | |||
107 | return buf; | 108 | return buf; |
108 | } | 109 | } |
109 | 110 | ||
110 | int dirty_tree_block(struct btrfs_root *root, struct btrfs_buffer *buf) | 111 | int dirty_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
112 | struct btrfs_buffer *buf) | ||
111 | { | 113 | { |
112 | if (!list_empty(&buf->dirty)) | 114 | if (!list_empty(&buf->dirty)) |
113 | return 0; | 115 | return 0; |
@@ -116,7 +118,8 @@ int dirty_tree_block(struct btrfs_root *root, struct btrfs_buffer *buf) | |||
116 | return 0; | 118 | return 0; |
117 | } | 119 | } |
118 | 120 | ||
119 | int clean_tree_block(struct btrfs_root *root, struct btrfs_buffer *buf) | 121 | int clean_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
122 | struct btrfs_buffer *buf) | ||
120 | { | 123 | { |
121 | if (!list_empty(&buf->dirty)) { | 124 | if (!list_empty(&buf->dirty)) { |
122 | list_del_init(&buf->dirty); | 125 | list_del_init(&buf->dirty); |
@@ -125,7 +128,8 @@ int clean_tree_block(struct btrfs_root *root, struct btrfs_buffer *buf) | |||
125 | return 0; | 128 | return 0; |
126 | } | 129 | } |
127 | 130 | ||
128 | int write_tree_block(struct btrfs_root *root, struct btrfs_buffer *buf) | 131 | int write_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
132 | struct btrfs_buffer *buf) | ||
129 | { | 133 | { |
130 | u64 blocknr = buf->blocknr; | 134 | u64 blocknr = buf->blocknr; |
131 | loff_t offset = blocknr * root->blocksize; | 135 | loff_t offset = blocknr * root->blocksize; |
@@ -139,7 +143,8 @@ int write_tree_block(struct btrfs_root *root, struct btrfs_buffer *buf) | |||
139 | return 0; | 143 | return 0; |
140 | } | 144 | } |
141 | 145 | ||
142 | static int __commit_transaction(struct btrfs_root *root) | 146 | static int __commit_transaction(struct btrfs_trans_handle *trans, struct |
147 | btrfs_root *root) | ||
143 | { | 148 | { |
144 | struct btrfs_buffer *b; | 149 | struct btrfs_buffer *b; |
145 | int ret = 0; | 150 | int ret = 0; |
@@ -147,7 +152,7 @@ static int __commit_transaction(struct btrfs_root *root) | |||
147 | while(!list_empty(&root->trans)) { | 152 | while(!list_empty(&root->trans)) { |
148 | b = list_entry(root->trans.next, struct btrfs_buffer, dirty); | 153 | b = list_entry(root->trans.next, struct btrfs_buffer, dirty); |
149 | list_del_init(&b->dirty); | 154 | list_del_init(&b->dirty); |
150 | wret = write_tree_block(root, b); | 155 | wret = write_tree_block(trans, root, b); |
151 | if (wret) | 156 | if (wret) |
152 | ret = wret; | 157 | ret = wret; |
153 | btrfs_block_release(root, b); | 158 | btrfs_block_release(root, b); |
@@ -155,8 +160,9 @@ static int __commit_transaction(struct btrfs_root *root) | |||
155 | return ret; | 160 | return ret; |
156 | } | 161 | } |
157 | 162 | ||
158 | static int commit_extent_and_tree_roots(struct btrfs_root *tree_root, | 163 | static int commit_extent_and_tree_roots(struct btrfs_trans_handle *trans, |
159 | struct btrfs_root *extent_root) | 164 | struct btrfs_root *tree_root, struct |
165 | btrfs_root *extent_root) | ||
160 | { | 166 | { |
161 | int ret; | 167 | int ret; |
162 | u64 old_extent_block; | 168 | u64 old_extent_block; |
@@ -167,24 +173,24 @@ static int commit_extent_and_tree_roots(struct btrfs_root *tree_root, | |||
167 | break; | 173 | break; |
168 | btrfs_set_root_blocknr(&extent_root->root_item, | 174 | btrfs_set_root_blocknr(&extent_root->root_item, |
169 | extent_root->node->blocknr); | 175 | extent_root->node->blocknr); |
170 | ret = btrfs_update_root(tree_root, | 176 | ret = btrfs_update_root(trans, tree_root, |
171 | &extent_root->root_key, | 177 | &extent_root->root_key, |
172 | &extent_root->root_item); | 178 | &extent_root->root_item); |
173 | BUG_ON(ret); | 179 | BUG_ON(ret); |
174 | } | 180 | } |
175 | __commit_transaction(extent_root); | 181 | __commit_transaction(trans, extent_root); |
176 | __commit_transaction(tree_root); | 182 | __commit_transaction(trans, tree_root); |
177 | return 0; | 183 | return 0; |
178 | } | 184 | } |
179 | 185 | ||
180 | int btrfs_commit_transaction(struct btrfs_root *root, | 186 | int btrfs_commit_transaction(struct btrfs_trans_handle *trans, struct |
181 | struct btrfs_super_block *s) | 187 | btrfs_root *root, struct btrfs_super_block *s) |
182 | { | 188 | { |
183 | int ret = 0; | 189 | int ret = 0; |
184 | struct btrfs_buffer *snap = root->commit_root; | 190 | struct btrfs_buffer *snap = root->commit_root; |
185 | struct btrfs_key snap_key; | 191 | struct btrfs_key snap_key; |
186 | 192 | ||
187 | ret = __commit_transaction(root); | 193 | ret = __commit_transaction(trans, root); |
188 | BUG_ON(ret); | 194 | BUG_ON(ret); |
189 | 195 | ||
190 | if (root->commit_root == root->node) | 196 | if (root->commit_root == root->node) |
@@ -194,23 +200,24 @@ int btrfs_commit_transaction(struct btrfs_root *root, | |||
194 | root->root_key.offset++; | 200 | root->root_key.offset++; |
195 | 201 | ||
196 | btrfs_set_root_blocknr(&root->root_item, root->node->blocknr); | 202 | btrfs_set_root_blocknr(&root->root_item, root->node->blocknr); |
197 | ret = btrfs_insert_root(root->tree_root, &root->root_key, | 203 | ret = btrfs_insert_root(trans, root->tree_root, &root->root_key, |
198 | &root->root_item); | 204 | &root->root_item); |
199 | BUG_ON(ret); | 205 | BUG_ON(ret); |
200 | 206 | ||
201 | ret = commit_extent_and_tree_roots(root->tree_root, root->extent_root); | 207 | ret = commit_extent_and_tree_roots(trans, root->tree_root, |
208 | root->extent_root); | ||
202 | BUG_ON(ret); | 209 | BUG_ON(ret); |
203 | 210 | ||
204 | write_ctree_super(root, s); | 211 | write_ctree_super(trans, root, s); |
205 | btrfs_finish_extent_commit(root->extent_root); | 212 | btrfs_finish_extent_commit(trans, root->extent_root); |
206 | btrfs_finish_extent_commit(root->tree_root); | 213 | btrfs_finish_extent_commit(trans, root->tree_root); |
207 | 214 | ||
208 | root->commit_root = root->node; | 215 | root->commit_root = root->node; |
209 | root->node->count++; | 216 | root->node->count++; |
210 | ret = btrfs_drop_snapshot(root, snap); | 217 | ret = btrfs_drop_snapshot(trans, root, snap); |
211 | BUG_ON(ret); | 218 | BUG_ON(ret); |
212 | 219 | ||
213 | ret = btrfs_del_root(root->tree_root, &snap_key); | 220 | ret = btrfs_del_root(trans, root->tree_root, &snap_key); |
214 | BUG_ON(ret); | 221 | BUG_ON(ret); |
215 | 222 | ||
216 | return ret; | 223 | return ret; |
@@ -312,7 +319,8 @@ struct btrfs_root *open_ctree(char *filename, struct btrfs_super_block *super) | |||
312 | return root; | 319 | return root; |
313 | } | 320 | } |
314 | 321 | ||
315 | int write_ctree_super(struct btrfs_root *root, struct btrfs_super_block *s) | 322 | int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root |
323 | *root, struct btrfs_super_block *s) | ||
316 | { | 324 | { |
317 | int ret; | 325 | int ret; |
318 | btrfs_set_super_root(s, root->tree_root->node->blocknr); | 326 | btrfs_set_super_root(s, root->tree_root->node->blocknr); |
@@ -338,10 +346,14 @@ static int drop_cache(struct btrfs_root *root) | |||
338 | int close_ctree(struct btrfs_root *root, struct btrfs_super_block *s) | 346 | int close_ctree(struct btrfs_root *root, struct btrfs_super_block *s) |
339 | { | 347 | { |
340 | int ret; | 348 | int ret; |
341 | btrfs_commit_transaction(root, s); | 349 | struct btrfs_trans_handle *trans; |
342 | ret = commit_extent_and_tree_roots(root->tree_root, root->extent_root); | 350 | |
351 | trans = root->running_transaction; | ||
352 | btrfs_commit_transaction(trans, root, s); | ||
353 | ret = commit_extent_and_tree_roots(trans, root->tree_root, | ||
354 | root->extent_root); | ||
343 | BUG_ON(ret); | 355 | BUG_ON(ret); |
344 | write_ctree_super(root, s); | 356 | write_ctree_super(trans, root, s); |
345 | drop_cache(root->extent_root); | 357 | drop_cache(root->extent_root); |
346 | drop_cache(root->tree_root); | 358 | drop_cache(root->tree_root); |
347 | drop_cache(root); | 359 | drop_cache(root); |
diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h index 5771bb90acb2..24a9e77c8311 100644 --- a/fs/btrfs/disk-io.h +++ b/fs/btrfs/disk-io.h | |||
@@ -15,15 +15,19 @@ struct btrfs_buffer { | |||
15 | 15 | ||
16 | struct btrfs_buffer *read_tree_block(struct btrfs_root *root, u64 blocknr); | 16 | struct btrfs_buffer *read_tree_block(struct btrfs_root *root, u64 blocknr); |
17 | struct btrfs_buffer *find_tree_block(struct btrfs_root *root, u64 blocknr); | 17 | struct btrfs_buffer *find_tree_block(struct btrfs_root *root, u64 blocknr); |
18 | int write_tree_block(struct btrfs_root *root, struct btrfs_buffer *buf); | 18 | int write_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
19 | int dirty_tree_block(struct btrfs_root *root, struct btrfs_buffer *buf); | 19 | struct btrfs_buffer *buf); |
20 | int clean_tree_block(struct btrfs_root *root, struct btrfs_buffer *buf); | 20 | int dirty_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
21 | int btrfs_commit_transaction(struct btrfs_root *root, | 21 | struct btrfs_buffer *buf); |
22 | struct btrfs_super_block *s); | 22 | int clean_tree_block(struct btrfs_trans_handle *trans, |
23 | struct btrfs_root *root, struct btrfs_buffer *buf); | ||
24 | int btrfs_commit_transaction(struct btrfs_trans_handle *trans, struct btrfs_root | ||
25 | *root, struct btrfs_super_block *s); | ||
23 | struct btrfs_root *open_ctree(char *filename, struct btrfs_super_block *s); | 26 | struct btrfs_root *open_ctree(char *filename, struct btrfs_super_block *s); |
24 | int close_ctree(struct btrfs_root *root, struct btrfs_super_block *s); | 27 | int close_ctree(struct btrfs_root *root, struct btrfs_super_block *s); |
25 | void btrfs_block_release(struct btrfs_root *root, struct btrfs_buffer *buf); | 28 | void btrfs_block_release(struct btrfs_root *root, struct btrfs_buffer *buf); |
26 | int write_ctree_super(struct btrfs_root *root, struct btrfs_super_block *s); | 29 | int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
30 | struct btrfs_super_block *s); | ||
27 | int mkfs(int fd, u64 num_blocks, u32 blocksize); | 31 | int mkfs(int fd, u64 num_blocks, u32 blocksize); |
28 | 32 | ||
29 | #define BTRFS_SUPER_INFO_OFFSET (16 * 1024) | 33 | #define BTRFS_SUPER_INFO_OFFSET (16 * 1024) |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 4a40282b45f7..c29b92d440e0 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -5,12 +5,15 @@ | |||
5 | #include "ctree.h" | 5 | #include "ctree.h" |
6 | #include "disk-io.h" | 6 | #include "disk-io.h" |
7 | #include "print-tree.h" | 7 | #include "print-tree.h" |
8 | #include "transaction.h" | ||
8 | 9 | ||
9 | static int find_free_extent(struct btrfs_root *orig_root, u64 num_blocks, | 10 | static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root |
10 | u64 search_start, u64 search_end, | 11 | *orig_root, u64 num_blocks, u64 search_start, u64 |
11 | struct btrfs_key *ins); | 12 | search_end, struct btrfs_key *ins); |
12 | static int finish_current_insert(struct btrfs_root *extent_root); | 13 | static int finish_current_insert(struct btrfs_trans_handle *trans, struct |
13 | static int run_pending(struct btrfs_root *extent_root); | 14 | btrfs_root *extent_root); |
15 | static int run_pending(struct btrfs_trans_handle *trans, struct btrfs_root | ||
16 | *extent_root); | ||
14 | 17 | ||
15 | /* | 18 | /* |
16 | * pending extents are blocks that we're trying to allocate in the extent | 19 | * pending extents are blocks that we're trying to allocate in the extent |
@@ -21,7 +24,8 @@ static int run_pending(struct btrfs_root *extent_root); | |||
21 | */ | 24 | */ |
22 | #define CTREE_EXTENT_PENDING_DEL 0 | 25 | #define CTREE_EXTENT_PENDING_DEL 0 |
23 | 26 | ||
24 | static int inc_block_ref(struct btrfs_root *root, u64 blocknr) | 27 | static int inc_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root |
28 | *root, u64 blocknr) | ||
25 | { | 29 | { |
26 | struct btrfs_path path; | 30 | struct btrfs_path path; |
27 | int ret; | 31 | int ret; |
@@ -31,13 +35,13 @@ static int inc_block_ref(struct btrfs_root *root, u64 blocknr) | |||
31 | struct btrfs_key ins; | 35 | struct btrfs_key ins; |
32 | u32 refs; | 36 | u32 refs; |
33 | 37 | ||
34 | find_free_extent(root->extent_root, 0, 0, (u64)-1, &ins); | 38 | find_free_extent(trans, root->extent_root, 0, 0, (u64)-1, &ins); |
35 | btrfs_init_path(&path); | 39 | btrfs_init_path(&path); |
36 | key.objectid = blocknr; | 40 | key.objectid = blocknr; |
37 | key.flags = 0; | 41 | key.flags = 0; |
38 | btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); | 42 | btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); |
39 | key.offset = 1; | 43 | key.offset = 1; |
40 | ret = btrfs_search_slot(root->extent_root, &key, &path, 0, 1); | 44 | ret = btrfs_search_slot(trans, root->extent_root, &key, &path, 0, 1); |
41 | if (ret != 0) | 45 | if (ret != 0) |
42 | BUG(); | 46 | BUG(); |
43 | BUG_ON(ret != 0); | 47 | BUG_ON(ret != 0); |
@@ -48,12 +52,13 @@ static int inc_block_ref(struct btrfs_root *root, u64 blocknr) | |||
48 | 52 | ||
49 | BUG_ON(list_empty(&path.nodes[0]->dirty)); | 53 | BUG_ON(list_empty(&path.nodes[0]->dirty)); |
50 | btrfs_release_path(root->extent_root, &path); | 54 | btrfs_release_path(root->extent_root, &path); |
51 | finish_current_insert(root->extent_root); | 55 | finish_current_insert(trans, root->extent_root); |
52 | run_pending(root->extent_root); | 56 | run_pending(trans, root->extent_root); |
53 | return 0; | 57 | return 0; |
54 | } | 58 | } |
55 | 59 | ||
56 | static int lookup_block_ref(struct btrfs_root *root, u64 blocknr, u32 *refs) | 60 | static int lookup_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root |
61 | *root, u64 blocknr, u32 *refs) | ||
57 | { | 62 | { |
58 | struct btrfs_path path; | 63 | struct btrfs_path path; |
59 | int ret; | 64 | int ret; |
@@ -65,7 +70,7 @@ static int lookup_block_ref(struct btrfs_root *root, u64 blocknr, u32 *refs) | |||
65 | key.offset = 1; | 70 | key.offset = 1; |
66 | key.flags = 0; | 71 | key.flags = 0; |
67 | btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); | 72 | btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); |
68 | ret = btrfs_search_slot(root->extent_root, &key, &path, 0, 0); | 73 | ret = btrfs_search_slot(trans, root->extent_root, &key, &path, 0, 0); |
69 | if (ret != 0) | 74 | if (ret != 0) |
70 | BUG(); | 75 | BUG(); |
71 | l = &path.nodes[0]->leaf; | 76 | l = &path.nodes[0]->leaf; |
@@ -75,7 +80,8 @@ static int lookup_block_ref(struct btrfs_root *root, u64 blocknr, u32 *refs) | |||
75 | return 0; | 80 | return 0; |
76 | } | 81 | } |
77 | 82 | ||
78 | int btrfs_inc_ref(struct btrfs_root *root, struct btrfs_buffer *buf) | 83 | int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
84 | struct btrfs_buffer *buf) | ||
79 | { | 85 | { |
80 | u64 blocknr; | 86 | u64 blocknr; |
81 | int i; | 87 | int i; |
@@ -87,12 +93,13 @@ int btrfs_inc_ref(struct btrfs_root *root, struct btrfs_buffer *buf) | |||
87 | 93 | ||
88 | for (i = 0; i < btrfs_header_nritems(&buf->node.header); i++) { | 94 | for (i = 0; i < btrfs_header_nritems(&buf->node.header); i++) { |
89 | blocknr = btrfs_node_blockptr(&buf->node, i); | 95 | blocknr = btrfs_node_blockptr(&buf->node, i); |
90 | inc_block_ref(root, blocknr); | 96 | inc_block_ref(trans, root, blocknr); |
91 | } | 97 | } |
92 | return 0; | 98 | return 0; |
93 | } | 99 | } |
94 | 100 | ||
95 | int btrfs_finish_extent_commit(struct btrfs_root *root) | 101 | int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct |
102 | btrfs_root *root) | ||
96 | { | 103 | { |
97 | unsigned long gang[8]; | 104 | unsigned long gang[8]; |
98 | u64 first = 0; | 105 | u64 first = 0; |
@@ -116,7 +123,8 @@ int btrfs_finish_extent_commit(struct btrfs_root *root) | |||
116 | return 0; | 123 | return 0; |
117 | } | 124 | } |
118 | 125 | ||
119 | static int finish_current_insert(struct btrfs_root *extent_root) | 126 | static int finish_current_insert(struct btrfs_trans_handle *trans, struct |
127 | btrfs_root *extent_root) | ||
120 | { | 128 | { |
121 | struct btrfs_key ins; | 129 | struct btrfs_key ins; |
122 | struct btrfs_extent_item extent_item; | 130 | struct btrfs_extent_item extent_item; |
@@ -132,8 +140,8 @@ static int finish_current_insert(struct btrfs_root *extent_root) | |||
132 | 140 | ||
133 | for (i = 0; i < extent_root->current_insert.flags; i++) { | 141 | for (i = 0; i < extent_root->current_insert.flags; i++) { |
134 | ins.objectid = extent_root->current_insert.objectid + i; | 142 | ins.objectid = extent_root->current_insert.objectid + i; |
135 | ret = btrfs_insert_item(extent_root, &ins, &extent_item, | 143 | ret = btrfs_insert_item(trans, extent_root, &ins, &extent_item, |
136 | sizeof(extent_item)); | 144 | sizeof(extent_item)); |
137 | BUG_ON(ret); | 145 | BUG_ON(ret); |
138 | } | 146 | } |
139 | extent_root->current_insert.offset = 0; | 147 | extent_root->current_insert.offset = 0; |
@@ -143,8 +151,8 @@ static int finish_current_insert(struct btrfs_root *extent_root) | |||
143 | /* | 151 | /* |
144 | * remove an extent from the root, returns 0 on success | 152 | * remove an extent from the root, returns 0 on success |
145 | */ | 153 | */ |
146 | static int __free_extent(struct btrfs_root *root, u64 blocknr, u64 num_blocks, | 154 | static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root |
147 | int pin) | 155 | *root, u64 blocknr, u64 num_blocks, int pin) |
148 | { | 156 | { |
149 | struct btrfs_path path; | 157 | struct btrfs_path path; |
150 | struct btrfs_key key; | 158 | struct btrfs_key key; |
@@ -160,9 +168,9 @@ static int __free_extent(struct btrfs_root *root, u64 blocknr, u64 num_blocks, | |||
160 | btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); | 168 | btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); |
161 | key.offset = num_blocks; | 169 | key.offset = num_blocks; |
162 | 170 | ||
163 | find_free_extent(root, 0, 0, (u64)-1, &ins); | 171 | find_free_extent(trans, root, 0, 0, (u64)-1, &ins); |
164 | btrfs_init_path(&path); | 172 | btrfs_init_path(&path); |
165 | ret = btrfs_search_slot(extent_root, &key, &path, -1, 1); | 173 | ret = btrfs_search_slot(trans, extent_root, &key, &path, -1, 1); |
166 | if (ret) { | 174 | if (ret) { |
167 | printf("failed to find %Lu\n", key.objectid); | 175 | printf("failed to find %Lu\n", key.objectid); |
168 | btrfs_print_tree(extent_root, extent_root->node); | 176 | btrfs_print_tree(extent_root, extent_root->node); |
@@ -183,14 +191,14 @@ static int __free_extent(struct btrfs_root *root, u64 blocknr, u64 num_blocks, | |||
183 | BUG_ON(err); | 191 | BUG_ON(err); |
184 | radix_tree_preload_end(); | 192 | radix_tree_preload_end(); |
185 | } | 193 | } |
186 | ret = btrfs_del_item(extent_root, &path); | 194 | ret = btrfs_del_item(trans, extent_root, &path); |
187 | if (!pin && extent_root->last_insert.objectid > blocknr) | 195 | if (!pin && extent_root->last_insert.objectid > blocknr) |
188 | extent_root->last_insert.objectid = blocknr; | 196 | extent_root->last_insert.objectid = blocknr; |
189 | if (ret) | 197 | if (ret) |
190 | BUG(); | 198 | BUG(); |
191 | } | 199 | } |
192 | btrfs_release_path(extent_root, &path); | 200 | btrfs_release_path(extent_root, &path); |
193 | finish_current_insert(extent_root); | 201 | finish_current_insert(trans, extent_root); |
194 | return ret; | 202 | return ret; |
195 | } | 203 | } |
196 | 204 | ||
@@ -198,7 +206,8 @@ static int __free_extent(struct btrfs_root *root, u64 blocknr, u64 num_blocks, | |||
198 | * find all the blocks marked as pending in the radix tree and remove | 206 | * find all the blocks marked as pending in the radix tree and remove |
199 | * them from the extent map | 207 | * them from the extent map |
200 | */ | 208 | */ |
201 | static int del_pending_extents(struct btrfs_root *extent_root) | 209 | static int del_pending_extents(struct btrfs_trans_handle *trans, struct |
210 | btrfs_root *extent_root) | ||
202 | { | 211 | { |
203 | int ret; | 212 | int ret; |
204 | struct btrfs_buffer *gang[4]; | 213 | struct btrfs_buffer *gang[4]; |
@@ -212,7 +221,7 @@ static int del_pending_extents(struct btrfs_root *extent_root) | |||
212 | if (!ret) | 221 | if (!ret) |
213 | break; | 222 | break; |
214 | for (i = 0; i < ret; i++) { | 223 | for (i = 0; i < ret; i++) { |
215 | ret = __free_extent(extent_root, | 224 | ret = __free_extent(trans, extent_root, |
216 | gang[i]->blocknr, 1, 1); | 225 | gang[i]->blocknr, 1, 1); |
217 | radix_tree_tag_clear(&extent_root->cache_radix, | 226 | radix_tree_tag_clear(&extent_root->cache_radix, |
218 | gang[i]->blocknr, | 227 | gang[i]->blocknr, |
@@ -223,11 +232,12 @@ static int del_pending_extents(struct btrfs_root *extent_root) | |||
223 | return 0; | 232 | return 0; |
224 | } | 233 | } |
225 | 234 | ||
226 | static int run_pending(struct btrfs_root *extent_root) | 235 | static int run_pending(struct btrfs_trans_handle *trans, struct btrfs_root |
236 | *extent_root) | ||
227 | { | 237 | { |
228 | while(radix_tree_tagged(&extent_root->cache_radix, | 238 | while(radix_tree_tagged(&extent_root->cache_radix, |
229 | CTREE_EXTENT_PENDING_DEL)) | 239 | CTREE_EXTENT_PENDING_DEL)) |
230 | del_pending_extents(extent_root); | 240 | del_pending_extents(trans, extent_root); |
231 | return 0; | 241 | return 0; |
232 | } | 242 | } |
233 | 243 | ||
@@ -235,8 +245,8 @@ static int run_pending(struct btrfs_root *extent_root) | |||
235 | /* | 245 | /* |
236 | * remove an extent from the root, returns 0 on success | 246 | * remove an extent from the root, returns 0 on success |
237 | */ | 247 | */ |
238 | int btrfs_free_extent(struct btrfs_root *root, u64 blocknr, u64 num_blocks, | 248 | int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root |
239 | int pin) | 249 | *root, u64 blocknr, u64 num_blocks, int pin) |
240 | { | 250 | { |
241 | struct btrfs_root *extent_root = root->extent_root; | 251 | struct btrfs_root *extent_root = root->extent_root; |
242 | struct btrfs_buffer *t; | 252 | struct btrfs_buffer *t; |
@@ -249,8 +259,8 @@ int btrfs_free_extent(struct btrfs_root *root, u64 blocknr, u64 num_blocks, | |||
249 | CTREE_EXTENT_PENDING_DEL); | 259 | CTREE_EXTENT_PENDING_DEL); |
250 | return 0; | 260 | return 0; |
251 | } | 261 | } |
252 | ret = __free_extent(root, blocknr, num_blocks, pin); | 262 | ret = __free_extent(trans, root, blocknr, num_blocks, pin); |
253 | pending_ret = run_pending(root->extent_root); | 263 | pending_ret = run_pending(trans, root->extent_root); |
254 | return ret ? ret : pending_ret; | 264 | return ret ? ret : pending_ret; |
255 | } | 265 | } |
256 | 266 | ||
@@ -262,9 +272,9 @@ int btrfs_free_extent(struct btrfs_root *root, u64 blocknr, u64 num_blocks, | |||
262 | * ins->offset == number of blocks | 272 | * ins->offset == number of blocks |
263 | * Any available blocks before search_start are skipped. | 273 | * Any available blocks before search_start are skipped. |
264 | */ | 274 | */ |
265 | static int find_free_extent(struct btrfs_root *orig_root, u64 num_blocks, | 275 | static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root |
266 | u64 search_start, u64 search_end, | 276 | *orig_root, u64 num_blocks, u64 search_start, u64 |
267 | struct btrfs_key *ins) | 277 | search_end, struct btrfs_key *ins) |
268 | { | 278 | { |
269 | struct btrfs_path path; | 279 | struct btrfs_path path; |
270 | struct btrfs_key key; | 280 | struct btrfs_key key; |
@@ -290,7 +300,7 @@ check_failed: | |||
290 | ins->objectid = search_start; | 300 | ins->objectid = search_start; |
291 | ins->offset = 0; | 301 | ins->offset = 0; |
292 | start_found = 0; | 302 | start_found = 0; |
293 | ret = btrfs_search_slot(root, ins, &path, 0, 0); | 303 | ret = btrfs_search_slot(trans, root, ins, &path, 0, 0); |
294 | if (ret < 0) | 304 | if (ret < 0) |
295 | goto error; | 305 | goto error; |
296 | 306 | ||
@@ -367,9 +377,9 @@ error: | |||
367 | * | 377 | * |
368 | * returns 0 if everything worked, non-zero otherwise. | 378 | * returns 0 if everything worked, non-zero otherwise. |
369 | */ | 379 | */ |
370 | static int alloc_extent(struct btrfs_root *root, u64 num_blocks, | 380 | static int alloc_extent(struct btrfs_trans_handle *trans, struct btrfs_root |
371 | u64 search_start, u64 search_end, u64 owner, | 381 | *root, u64 num_blocks, u64 search_start, u64 |
372 | struct btrfs_key *ins) | 382 | search_end, u64 owner, struct btrfs_key *ins) |
373 | { | 383 | { |
374 | int ret; | 384 | int ret; |
375 | int pending_ret; | 385 | int pending_ret; |
@@ -389,16 +399,16 @@ static int alloc_extent(struct btrfs_root *root, u64 num_blocks, | |||
389 | extent_root->current_insert.flags++; | 399 | extent_root->current_insert.flags++; |
390 | return 0; | 400 | return 0; |
391 | } | 401 | } |
392 | ret = find_free_extent(root, num_blocks, search_start, | 402 | ret = find_free_extent(trans, root, num_blocks, search_start, |
393 | search_end, ins); | 403 | search_end, ins); |
394 | if (ret) | 404 | if (ret) |
395 | return ret; | 405 | return ret; |
396 | 406 | ||
397 | ret = btrfs_insert_item(extent_root, ins, &extent_item, | 407 | ret = btrfs_insert_item(trans, extent_root, ins, &extent_item, |
398 | sizeof(extent_item)); | 408 | sizeof(extent_item)); |
399 | 409 | ||
400 | finish_current_insert(extent_root); | 410 | finish_current_insert(trans, extent_root); |
401 | pending_ret = run_pending(extent_root); | 411 | pending_ret = run_pending(trans, extent_root); |
402 | if (ret) | 412 | if (ret) |
403 | return ret; | 413 | return ret; |
404 | if (pending_ret) | 414 | if (pending_ret) |
@@ -410,13 +420,14 @@ static int alloc_extent(struct btrfs_root *root, u64 num_blocks, | |||
410 | * helper function to allocate a block for a given tree | 420 | * helper function to allocate a block for a given tree |
411 | * returns the tree buffer or NULL. | 421 | * returns the tree buffer or NULL. |
412 | */ | 422 | */ |
413 | struct btrfs_buffer *btrfs_alloc_free_block(struct btrfs_root *root) | 423 | struct btrfs_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans, |
424 | struct btrfs_root *root) | ||
414 | { | 425 | { |
415 | struct btrfs_key ins; | 426 | struct btrfs_key ins; |
416 | int ret; | 427 | int ret; |
417 | struct btrfs_buffer *buf; | 428 | struct btrfs_buffer *buf; |
418 | 429 | ||
419 | ret = alloc_extent(root, 1, 0, (unsigned long)-1, | 430 | ret = alloc_extent(trans, root, 1, 0, (unsigned long)-1, |
420 | btrfs_header_parentid(&root->node->node.header), | 431 | btrfs_header_parentid(&root->node->node.header), |
421 | &ins); | 432 | &ins); |
422 | if (ret) { | 433 | if (ret) { |
@@ -424,7 +435,7 @@ struct btrfs_buffer *btrfs_alloc_free_block(struct btrfs_root *root) | |||
424 | return NULL; | 435 | return NULL; |
425 | } | 436 | } |
426 | buf = find_tree_block(root, ins.objectid); | 437 | buf = find_tree_block(root, ins.objectid); |
427 | dirty_tree_block(root, buf); | 438 | dirty_tree_block(trans, root, buf); |
428 | return buf; | 439 | return buf; |
429 | } | 440 | } |
430 | 441 | ||
@@ -432,8 +443,8 @@ struct btrfs_buffer *btrfs_alloc_free_block(struct btrfs_root *root) | |||
432 | * helper function for drop_snapshot, this walks down the tree dropping ref | 443 | * helper function for drop_snapshot, this walks down the tree dropping ref |
433 | * counts as it goes. | 444 | * counts as it goes. |
434 | */ | 445 | */ |
435 | static int walk_down_tree(struct btrfs_root *root, | 446 | static int walk_down_tree(struct btrfs_trans_handle *trans, struct btrfs_root |
436 | struct btrfs_path *path, int *level) | 447 | *root, struct btrfs_path *path, int *level) |
437 | { | 448 | { |
438 | struct btrfs_buffer *next; | 449 | struct btrfs_buffer *next; |
439 | struct btrfs_buffer *cur; | 450 | struct btrfs_buffer *cur; |
@@ -441,7 +452,8 @@ static int walk_down_tree(struct btrfs_root *root, | |||
441 | int ret; | 452 | int ret; |
442 | u32 refs; | 453 | u32 refs; |
443 | 454 | ||
444 | ret = lookup_block_ref(root, path->nodes[*level]->blocknr, &refs); | 455 | ret = lookup_block_ref(trans, root, path->nodes[*level]->blocknr, |
456 | &refs); | ||
445 | BUG_ON(ret); | 457 | BUG_ON(ret); |
446 | if (refs > 1) | 458 | if (refs > 1) |
447 | goto out; | 459 | goto out; |
@@ -454,10 +466,10 @@ static int walk_down_tree(struct btrfs_root *root, | |||
454 | btrfs_header_nritems(&cur->node.header)) | 466 | btrfs_header_nritems(&cur->node.header)) |
455 | break; | 467 | break; |
456 | blocknr = btrfs_node_blockptr(&cur->node, path->slots[*level]); | 468 | blocknr = btrfs_node_blockptr(&cur->node, path->slots[*level]); |
457 | ret = lookup_block_ref(root, blocknr, &refs); | 469 | ret = lookup_block_ref(trans, root, blocknr, &refs); |
458 | if (refs != 1 || *level == 1) { | 470 | if (refs != 1 || *level == 1) { |
459 | path->slots[*level]++; | 471 | path->slots[*level]++; |
460 | ret = btrfs_free_extent(root, blocknr, 1, 1); | 472 | ret = btrfs_free_extent(trans, root, blocknr, 1, 1); |
461 | BUG_ON(ret); | 473 | BUG_ON(ret); |
462 | continue; | 474 | continue; |
463 | } | 475 | } |
@@ -470,7 +482,8 @@ static int walk_down_tree(struct btrfs_root *root, | |||
470 | path->slots[*level] = 0; | 482 | path->slots[*level] = 0; |
471 | } | 483 | } |
472 | out: | 484 | out: |
473 | ret = btrfs_free_extent(root, path->nodes[*level]->blocknr, 1, 1); | 485 | ret = btrfs_free_extent(trans, root, path->nodes[*level]->blocknr, 1, |
486 | 1); | ||
474 | btrfs_block_release(root, path->nodes[*level]); | 487 | btrfs_block_release(root, path->nodes[*level]); |
475 | path->nodes[*level] = NULL; | 488 | path->nodes[*level] = NULL; |
476 | *level += 1; | 489 | *level += 1; |
@@ -483,8 +496,8 @@ out: | |||
483 | * to find the first node higher up where we haven't yet gone through | 496 | * to find the first node higher up where we haven't yet gone through |
484 | * all the slots | 497 | * all the slots |
485 | */ | 498 | */ |
486 | static int walk_up_tree(struct btrfs_root *root, struct btrfs_path *path, | 499 | static int walk_up_tree(struct btrfs_trans_handle *trans, struct btrfs_root |
487 | int *level) | 500 | *root, struct btrfs_path *path, int *level) |
488 | { | 501 | { |
489 | int i; | 502 | int i; |
490 | int slot; | 503 | int slot; |
@@ -497,8 +510,9 @@ static int walk_up_tree(struct btrfs_root *root, struct btrfs_path *path, | |||
497 | *level = i; | 510 | *level = i; |
498 | return 0; | 511 | return 0; |
499 | } else { | 512 | } else { |
500 | ret = btrfs_free_extent(root, | 513 | ret = btrfs_free_extent(trans, root, |
501 | path->nodes[*level]->blocknr, 1, 1); | 514 | path->nodes[*level]->blocknr, |
515 | 1, 1); | ||
502 | btrfs_block_release(root, path->nodes[*level]); | 516 | btrfs_block_release(root, path->nodes[*level]); |
503 | path->nodes[*level] = NULL; | 517 | path->nodes[*level] = NULL; |
504 | *level = i + 1; | 518 | *level = i + 1; |
@@ -513,7 +527,8 @@ static int walk_up_tree(struct btrfs_root *root, struct btrfs_path *path, | |||
513 | * the tree freeing any blocks that have a ref count of zero after being | 527 | * the tree freeing any blocks that have a ref count of zero after being |
514 | * decremented. | 528 | * decremented. |
515 | */ | 529 | */ |
516 | int btrfs_drop_snapshot(struct btrfs_root *root, struct btrfs_buffer *snap) | 530 | int btrfs_drop_snapshot(struct btrfs_trans_handle *trans, struct btrfs_root |
531 | *root, struct btrfs_buffer *snap) | ||
517 | { | 532 | { |
518 | int ret = 0; | 533 | int ret = 0; |
519 | int wret; | 534 | int wret; |
@@ -529,13 +544,13 @@ int btrfs_drop_snapshot(struct btrfs_root *root, struct btrfs_buffer *snap) | |||
529 | path.nodes[level] = snap; | 544 | path.nodes[level] = snap; |
530 | path.slots[level] = 0; | 545 | path.slots[level] = 0; |
531 | while(1) { | 546 | while(1) { |
532 | wret = walk_down_tree(root, &path, &level); | 547 | wret = walk_down_tree(trans, root, &path, &level); |
533 | if (wret > 0) | 548 | if (wret > 0) |
534 | break; | 549 | break; |
535 | if (wret < 0) | 550 | if (wret < 0) |
536 | ret = wret; | 551 | ret = wret; |
537 | 552 | ||
538 | wret = walk_up_tree(root, &path, &level); | 553 | wret = walk_up_tree(trans, root, &path, &level); |
539 | if (wret > 0) | 554 | if (wret > 0) |
540 | break; | 555 | break; |
541 | if (wret < 0) | 556 | if (wret < 0) |
diff --git a/fs/btrfs/inode-item.c b/fs/btrfs/inode-item.c index 4908f9afdf86..7caeb11e8756 100644 --- a/fs/btrfs/inode-item.c +++ b/fs/btrfs/inode-item.c | |||
@@ -4,9 +4,11 @@ | |||
4 | #include "radix-tree.h" | 4 | #include "radix-tree.h" |
5 | #include "ctree.h" | 5 | #include "ctree.h" |
6 | #include "disk-io.h" | 6 | #include "disk-io.h" |
7 | #include "transaction.h" | ||
7 | 8 | ||
8 | int btrfs_insert_inode(struct btrfs_root *root, u64 objectid, | 9 | int btrfs_insert_inode(struct btrfs_trans_handle *trans, struct btrfs_root |
9 | struct btrfs_inode_item *inode_item) | 10 | *root, u64 objectid, struct btrfs_inode_item |
11 | *inode_item) | ||
10 | { | 12 | { |
11 | struct btrfs_path path; | 13 | struct btrfs_path path; |
12 | struct btrfs_key key; | 14 | struct btrfs_key key; |
@@ -17,13 +19,14 @@ int btrfs_insert_inode(struct btrfs_root *root, u64 objectid, | |||
17 | key.offset = 0; | 19 | key.offset = 0; |
18 | 20 | ||
19 | btrfs_init_path(&path); | 21 | btrfs_init_path(&path); |
20 | ret = btrfs_insert_item(root, &key, inode_item, sizeof(*inode_item)); | 22 | ret = btrfs_insert_item(trans, root, &key, inode_item, |
23 | sizeof(*inode_item)); | ||
21 | btrfs_release_path(root, &path); | 24 | btrfs_release_path(root, &path); |
22 | return ret; | 25 | return ret; |
23 | } | 26 | } |
24 | 27 | ||
25 | int btrfs_lookup_inode(struct btrfs_root *root, struct btrfs_path *path, | 28 | int btrfs_lookup_inode(struct btrfs_trans_handle *trans, struct btrfs_root |
26 | u64 objectid, int mod) | 29 | *root, struct btrfs_path *path, u64 objectid, int mod) |
27 | { | 30 | { |
28 | struct btrfs_key key; | 31 | struct btrfs_key key; |
29 | int ins_len = mod < 0 ? -1 : 0; | 32 | int ins_len = mod < 0 ? -1 : 0; |
@@ -33,5 +36,5 @@ int btrfs_lookup_inode(struct btrfs_root *root, struct btrfs_path *path, | |||
33 | key.flags = 0; | 36 | key.flags = 0; |
34 | btrfs_set_key_type(&key, BTRFS_INODE_ITEM_KEY); | 37 | btrfs_set_key_type(&key, BTRFS_INODE_ITEM_KEY); |
35 | key.offset = 0; | 38 | key.offset = 0; |
36 | return btrfs_search_slot(root, &key, path, ins_len, cow); | 39 | return btrfs_search_slot(trans, root, &key, path, ins_len, cow); |
37 | } | 40 | } |
diff --git a/fs/btrfs/print-tree.h b/fs/btrfs/print-tree.h index 9236abda2a74..0882ca904eca 100644 --- a/fs/btrfs/print-tree.h +++ b/fs/btrfs/print-tree.h | |||
@@ -1,3 +1,5 @@ | |||
1 | 1 | #ifndef __PRINT_TREE_ | |
2 | #define __PRINT_TREE_ | ||
2 | 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); |
3 | void btrfs_print_tree(struct btrfs_root *root, struct btrfs_buffer *t); | 4 | void btrfs_print_tree(struct btrfs_root *root, struct btrfs_buffer *t); |
5 | #endif | ||
diff --git a/fs/btrfs/quick-test.c b/fs/btrfs/quick-test.c index 3a2571617121..d676577185d5 100644 --- a/fs/btrfs/quick-test.c +++ b/fs/btrfs/quick-test.c | |||
@@ -5,6 +5,7 @@ | |||
5 | #include "ctree.h" | 5 | #include "ctree.h" |
6 | #include "disk-io.h" | 6 | #include "disk-io.h" |
7 | #include "print-tree.h" | 7 | #include "print-tree.h" |
8 | #include "transaction.h" | ||
8 | 9 | ||
9 | /* for testing only */ | 10 | /* for testing only */ |
10 | int next_key(int i, int max_key) { | 11 | int next_key(int i, int max_key) { |
@@ -25,10 +26,12 @@ int main(int ac, char **av) { | |||
25 | struct btrfs_path path; | 26 | struct btrfs_path path; |
26 | struct btrfs_super_block super; | 27 | struct btrfs_super_block super; |
27 | struct btrfs_root *root; | 28 | struct btrfs_root *root; |
29 | struct btrfs_trans_handle *trans; | ||
28 | 30 | ||
29 | radix_tree_init(); | 31 | radix_tree_init(); |
30 | 32 | ||
31 | root = open_ctree("dbfile", &super); | 33 | root = open_ctree("dbfile", &super); |
34 | trans = btrfs_start_transaction(root, 1); | ||
32 | srand(55); | 35 | srand(55); |
33 | ins.flags = 0; | 36 | ins.flags = 0; |
34 | btrfs_set_key_type(&ins, BTRFS_STRING_ITEM_KEY); | 37 | btrfs_set_key_type(&ins, BTRFS_STRING_ITEM_KEY); |
@@ -41,12 +44,12 @@ int main(int ac, char **av) { | |||
41 | fprintf(stderr, "insert %d:%d\n", num, i); | 44 | fprintf(stderr, "insert %d:%d\n", num, i); |
42 | ins.objectid = num; | 45 | ins.objectid = num; |
43 | ins.offset = 0; | 46 | ins.offset = 0; |
44 | ret = btrfs_insert_item(root, &ins, buf, strlen(buf)); | 47 | ret = btrfs_insert_item(trans, root, &ins, buf, strlen(buf)); |
45 | if (!ret) | 48 | if (!ret) |
46 | tree_size++; | 49 | tree_size++; |
47 | free(buf); | 50 | free(buf); |
48 | if (i == run_size - 5) { | 51 | if (i == run_size - 5) { |
49 | btrfs_commit_transaction(root, &super); | 52 | btrfs_commit_transaction(trans, root, &super); |
50 | } | 53 | } |
51 | 54 | ||
52 | } | 55 | } |
@@ -61,7 +64,7 @@ int main(int ac, char **av) { | |||
61 | btrfs_init_path(&path); | 64 | btrfs_init_path(&path); |
62 | if (i % 10000 == 0) | 65 | if (i % 10000 == 0) |
63 | fprintf(stderr, "search %d:%d\n", num, i); | 66 | fprintf(stderr, "search %d:%d\n", num, i); |
64 | ret = btrfs_search_slot(root, &ins, &path, 0, 0); | 67 | ret = btrfs_search_slot(trans, root, &ins, &path, 0, 0); |
65 | if (ret) { | 68 | if (ret) { |
66 | btrfs_print_tree(root, root->node); | 69 | btrfs_print_tree(root, root->node); |
67 | printf("unable to find %d\n", num); | 70 | printf("unable to find %d\n", num); |
@@ -83,11 +86,11 @@ int main(int ac, char **av) { | |||
83 | num = next_key(i, max_key); | 86 | num = next_key(i, max_key); |
84 | ins.objectid = num; | 87 | ins.objectid = num; |
85 | btrfs_init_path(&path); | 88 | btrfs_init_path(&path); |
86 | ret = btrfs_search_slot(root, &ins, &path, -1, 1); | 89 | ret = btrfs_search_slot(trans, root, &ins, &path, -1, 1); |
87 | if (!ret) { | 90 | if (!ret) { |
88 | if (i % 10000 == 0) | 91 | if (i % 10000 == 0) |
89 | fprintf(stderr, "del %d:%d\n", num, i); | 92 | fprintf(stderr, "del %d:%d\n", num, i); |
90 | ret = btrfs_del_item(root, &path); | 93 | ret = btrfs_del_item(trans, root, &path); |
91 | if (ret != 0) | 94 | if (ret != 0) |
92 | BUG(); | 95 | BUG(); |
93 | tree_size--; | 96 | tree_size--; |
@@ -104,7 +107,7 @@ int main(int ac, char **av) { | |||
104 | ins.objectid = num; | 107 | ins.objectid = num; |
105 | if (i % 10000 == 0) | 108 | if (i % 10000 == 0) |
106 | fprintf(stderr, "insert %d:%d\n", num, i); | 109 | fprintf(stderr, "insert %d:%d\n", num, i); |
107 | ret = btrfs_insert_item(root, &ins, buf, strlen(buf)); | 110 | ret = btrfs_insert_item(trans, root, &ins, buf, strlen(buf)); |
108 | if (!ret) | 111 | if (!ret) |
109 | tree_size++; | 112 | tree_size++; |
110 | free(buf); | 113 | free(buf); |
@@ -119,7 +122,7 @@ int main(int ac, char **av) { | |||
119 | btrfs_init_path(&path); | 122 | btrfs_init_path(&path); |
120 | if (i % 10000 == 0) | 123 | if (i % 10000 == 0) |
121 | fprintf(stderr, "search %d:%d\n", num, i); | 124 | fprintf(stderr, "search %d:%d\n", num, i); |
122 | ret = btrfs_search_slot(root, &ins, &path, 0, 0); | 125 | ret = btrfs_search_slot(trans, root, &ins, &path, 0, 0); |
123 | if (ret) { | 126 | if (ret) { |
124 | btrfs_print_tree(root, root->node); | 127 | btrfs_print_tree(root, root->node); |
125 | printf("unable to find %d\n", num); | 128 | printf("unable to find %d\n", num); |
@@ -134,7 +137,7 @@ int main(int ac, char **av) { | |||
134 | int slot; | 137 | int slot; |
135 | ins.objectid = (u64)-1; | 138 | ins.objectid = (u64)-1; |
136 | btrfs_init_path(&path); | 139 | btrfs_init_path(&path); |
137 | ret = btrfs_search_slot(root, &ins, &path, -1, 1); | 140 | ret = btrfs_search_slot(trans, root, &ins, &path, -1, 1); |
138 | if (ret == 0) | 141 | if (ret == 0) |
139 | BUG(); | 142 | BUG(); |
140 | 143 | ||
@@ -150,7 +153,7 @@ int main(int ac, char **av) { | |||
150 | btrfs_disk_key_to_cpu(&last, &leaf->items[slot].key); | 153 | btrfs_disk_key_to_cpu(&last, &leaf->items[slot].key); |
151 | if (tree_size % 10000 == 0) | 154 | if (tree_size % 10000 == 0) |
152 | printf("big del %d:%d\n", tree_size, i); | 155 | printf("big del %d:%d\n", tree_size, i); |
153 | ret = btrfs_del_item(root, &path); | 156 | ret = btrfs_del_item(trans, root, &path); |
154 | if (ret != 0) { | 157 | if (ret != 0) { |
155 | printf("del_item returned %d\n", ret); | 158 | printf("del_item returned %d\n", ret); |
156 | BUG(); | 159 | BUG(); |
@@ -165,7 +168,7 @@ int main(int ac, char **av) { | |||
165 | printf("map before commit\n"); | 168 | printf("map before commit\n"); |
166 | btrfs_print_tree(root->extent_root, root->extent_root->node); | 169 | btrfs_print_tree(root->extent_root, root->extent_root->node); |
167 | */ | 170 | */ |
168 | btrfs_commit_transaction(root, &super); | 171 | btrfs_commit_transaction(trans, root, &super); |
169 | printf("tree size is now %d\n", tree_size); | 172 | printf("tree size is now %d\n", tree_size); |
170 | printf("root %p commit root %p\n", root->node, root->commit_root); | 173 | printf("root %p commit root %p\n", root->node, root->commit_root); |
171 | printf("map tree\n"); | 174 | printf("map tree\n"); |
diff --git a/fs/btrfs/random-test.c b/fs/btrfs/random-test.c index f05135f13f9a..3a38ae7a886d 100644 --- a/fs/btrfs/random-test.c +++ b/fs/btrfs/random-test.c | |||
@@ -6,6 +6,7 @@ | |||
6 | #include "ctree.h" | 6 | #include "ctree.h" |
7 | #include "disk-io.h" | 7 | #include "disk-io.h" |
8 | #include "print-tree.h" | 8 | #include "print-tree.h" |
9 | #include "transaction.h" | ||
9 | 10 | ||
10 | int keep_running = 1; | 11 | int keep_running = 1; |
11 | struct btrfs_super_block super; | 12 | struct btrfs_super_block super; |
@@ -37,7 +38,8 @@ again: | |||
37 | return 0; | 38 | return 0; |
38 | } | 39 | } |
39 | 40 | ||
40 | static int ins_one(struct btrfs_root *root, struct radix_tree_root *radix) | 41 | static int ins_one(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
42 | struct radix_tree_root *radix) | ||
41 | { | 43 | { |
42 | struct btrfs_path path; | 44 | struct btrfs_path path; |
43 | struct btrfs_key key; | 45 | struct btrfs_key key; |
@@ -47,7 +49,7 @@ static int ins_one(struct btrfs_root *root, struct radix_tree_root *radix) | |||
47 | btrfs_init_path(&path); | 49 | btrfs_init_path(&path); |
48 | ret = setup_key(radix, &key, 0); | 50 | ret = setup_key(radix, &key, 0); |
49 | sprintf(buf, "str-%Lu\n", key.objectid); | 51 | sprintf(buf, "str-%Lu\n", key.objectid); |
50 | ret = btrfs_insert_item(root, &key, buf, strlen(buf)); | 52 | ret = btrfs_insert_item(trans, root, &key, buf, strlen(buf)); |
51 | if (ret) | 53 | if (ret) |
52 | goto error; | 54 | goto error; |
53 | oid = (unsigned long)key.objectid; | 55 | oid = (unsigned long)key.objectid; |
@@ -62,7 +64,8 @@ error: | |||
62 | return -1; | 64 | return -1; |
63 | } | 65 | } |
64 | 66 | ||
65 | static int insert_dup(struct btrfs_root *root, struct radix_tree_root *radix) | 67 | static int insert_dup(struct btrfs_trans_handle *trans, struct btrfs_root |
68 | *root, struct radix_tree_root *radix) | ||
66 | { | 69 | { |
67 | struct btrfs_path path; | 70 | struct btrfs_path path; |
68 | struct btrfs_key key; | 71 | struct btrfs_key key; |
@@ -73,7 +76,7 @@ static int insert_dup(struct btrfs_root *root, struct radix_tree_root *radix) | |||
73 | if (ret < 0) | 76 | if (ret < 0) |
74 | return 0; | 77 | return 0; |
75 | sprintf(buf, "str-%Lu\n", key.objectid); | 78 | sprintf(buf, "str-%Lu\n", key.objectid); |
76 | ret = btrfs_insert_item(root, &key, buf, strlen(buf)); | 79 | ret = btrfs_insert_item(trans, root, &key, buf, strlen(buf)); |
77 | if (ret != -EEXIST) { | 80 | if (ret != -EEXIST) { |
78 | printf("insert on %Lu gave us %d\n", key.objectid, ret); | 81 | printf("insert on %Lu gave us %d\n", key.objectid, ret); |
79 | return 1; | 82 | return 1; |
@@ -81,7 +84,8 @@ static int insert_dup(struct btrfs_root *root, struct radix_tree_root *radix) | |||
81 | return 0; | 84 | return 0; |
82 | } | 85 | } |
83 | 86 | ||
84 | static int del_one(struct btrfs_root *root, struct radix_tree_root *radix) | 87 | static int del_one(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
88 | struct radix_tree_root *radix) | ||
85 | { | 89 | { |
86 | struct btrfs_path path; | 90 | struct btrfs_path path; |
87 | struct btrfs_key key; | 91 | struct btrfs_key key; |
@@ -91,10 +95,10 @@ static int del_one(struct btrfs_root *root, struct radix_tree_root *radix) | |||
91 | ret = setup_key(radix, &key, 1); | 95 | ret = setup_key(radix, &key, 1); |
92 | if (ret < 0) | 96 | if (ret < 0) |
93 | return 0; | 97 | return 0; |
94 | ret = btrfs_search_slot(root, &key, &path, -1, 1); | 98 | ret = btrfs_search_slot(trans, root, &key, &path, -1, 1); |
95 | if (ret) | 99 | if (ret) |
96 | goto error; | 100 | goto error; |
97 | ret = btrfs_del_item(root, &path); | 101 | ret = btrfs_del_item(trans, root, &path); |
98 | btrfs_release_path(root, &path); | 102 | btrfs_release_path(root, &path); |
99 | if (ret != 0) | 103 | if (ret != 0) |
100 | goto error; | 104 | goto error; |
@@ -107,7 +111,8 @@ error: | |||
107 | return -1; | 111 | return -1; |
108 | } | 112 | } |
109 | 113 | ||
110 | static int lookup_item(struct btrfs_root *root, struct radix_tree_root *radix) | 114 | static int lookup_item(struct btrfs_trans_handle *trans, struct btrfs_root |
115 | *root, struct radix_tree_root *radix) | ||
111 | { | 116 | { |
112 | struct btrfs_path path; | 117 | struct btrfs_path path; |
113 | struct btrfs_key key; | 118 | struct btrfs_key key; |
@@ -116,7 +121,7 @@ static int lookup_item(struct btrfs_root *root, struct radix_tree_root *radix) | |||
116 | ret = setup_key(radix, &key, 1); | 121 | ret = setup_key(radix, &key, 1); |
117 | if (ret < 0) | 122 | if (ret < 0) |
118 | return 0; | 123 | return 0; |
119 | ret = btrfs_search_slot(root, &key, &path, 0, 1); | 124 | ret = btrfs_search_slot(trans, root, &key, &path, 0, 1); |
120 | btrfs_release_path(root, &path); | 125 | btrfs_release_path(root, &path); |
121 | if (ret) | 126 | if (ret) |
122 | goto error; | 127 | goto error; |
@@ -126,7 +131,8 @@ error: | |||
126 | return -1; | 131 | return -1; |
127 | } | 132 | } |
128 | 133 | ||
129 | static int lookup_enoent(struct btrfs_root *root, struct radix_tree_root *radix) | 134 | static int lookup_enoent(struct btrfs_trans_handle *trans, struct btrfs_root |
135 | *root, struct radix_tree_root *radix) | ||
130 | { | 136 | { |
131 | struct btrfs_path path; | 137 | struct btrfs_path path; |
132 | struct btrfs_key key; | 138 | struct btrfs_key key; |
@@ -135,7 +141,7 @@ static int lookup_enoent(struct btrfs_root *root, struct radix_tree_root *radix) | |||
135 | ret = setup_key(radix, &key, 0); | 141 | ret = setup_key(radix, &key, 0); |
136 | if (ret < 0) | 142 | if (ret < 0) |
137 | return ret; | 143 | return ret; |
138 | ret = btrfs_search_slot(root, &key, &path, 0, 0); | 144 | ret = btrfs_search_slot(trans, root, &key, &path, 0, 0); |
139 | btrfs_release_path(root, &path); | 145 | btrfs_release_path(root, &path); |
140 | if (ret <= 0) | 146 | if (ret <= 0) |
141 | goto error; | 147 | goto error; |
@@ -145,8 +151,8 @@ error: | |||
145 | return -1; | 151 | return -1; |
146 | } | 152 | } |
147 | 153 | ||
148 | static int empty_tree(struct btrfs_root *root, struct radix_tree_root *radix, | 154 | static int empty_tree(struct btrfs_trans_handle *trans, struct btrfs_root |
149 | int nr) | 155 | *root, struct radix_tree_root *radix, int nr) |
150 | { | 156 | { |
151 | struct btrfs_path path; | 157 | struct btrfs_path path; |
152 | struct btrfs_key key; | 158 | struct btrfs_key key; |
@@ -162,7 +168,7 @@ static int empty_tree(struct btrfs_root *root, struct radix_tree_root *radix, | |||
162 | key.objectid = (unsigned long)-1; | 168 | key.objectid = (unsigned long)-1; |
163 | while(nr-- >= 0) { | 169 | while(nr-- >= 0) { |
164 | btrfs_init_path(&path); | 170 | btrfs_init_path(&path); |
165 | ret = btrfs_search_slot(root, &key, &path, -1, 1); | 171 | ret = btrfs_search_slot(trans, root, &key, &path, -1, 1); |
166 | if (ret < 0) { | 172 | if (ret < 0) { |
167 | btrfs_release_path(root, &path); | 173 | btrfs_release_path(root, &path); |
168 | return ret; | 174 | return ret; |
@@ -177,7 +183,7 @@ static int empty_tree(struct btrfs_root *root, struct radix_tree_root *radix, | |||
177 | slot = path.slots[0]; | 183 | slot = path.slots[0]; |
178 | found = btrfs_disk_key_objectid( | 184 | found = btrfs_disk_key_objectid( |
179 | &path.nodes[0]->leaf.items[slot].key); | 185 | &path.nodes[0]->leaf.items[slot].key); |
180 | ret = btrfs_del_item(root, &path); | 186 | ret = btrfs_del_item(trans, root, &path); |
181 | count++; | 187 | count++; |
182 | if (ret) { | 188 | if (ret) { |
183 | fprintf(stderr, | 189 | fprintf(stderr, |
@@ -198,19 +204,19 @@ error: | |||
198 | return -1; | 204 | return -1; |
199 | } | 205 | } |
200 | 206 | ||
201 | static int fill_tree(struct btrfs_root *root, struct radix_tree_root *radix, | 207 | static int fill_tree(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
202 | int count) | 208 | struct radix_tree_root *radix, int count) |
203 | { | 209 | { |
204 | int i; | 210 | int i; |
205 | int ret = 0; | 211 | int ret = 0; |
206 | for (i = 0; i < count; i++) { | 212 | for (i = 0; i < count; i++) { |
207 | ret = ins_one(root, radix); | 213 | ret = ins_one(trans, root, radix); |
208 | if (ret) { | 214 | if (ret) { |
209 | fprintf(stderr, "fill failed\n"); | 215 | fprintf(stderr, "fill failed\n"); |
210 | goto out; | 216 | goto out; |
211 | } | 217 | } |
212 | if (i % 1000 == 0) { | 218 | if (i % 1000 == 0) { |
213 | ret = btrfs_commit_transaction(root, &super); | 219 | ret = btrfs_commit_transaction(trans, root, &super); |
214 | if (ret) { | 220 | if (ret) { |
215 | fprintf(stderr, "fill commit failed\n"); | 221 | fprintf(stderr, "fill commit failed\n"); |
216 | return ret; | 222 | return ret; |
@@ -226,7 +232,8 @@ out: | |||
226 | return ret; | 232 | return ret; |
227 | } | 233 | } |
228 | 234 | ||
229 | static int bulk_op(struct btrfs_root *root, struct radix_tree_root *radix) | 235 | static int bulk_op(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
236 | struct radix_tree_root *radix) | ||
230 | { | 237 | { |
231 | int ret; | 238 | int ret; |
232 | int nr = rand() % 5000; | 239 | int nr = rand() % 5000; |
@@ -235,17 +242,18 @@ static int bulk_op(struct btrfs_root *root, struct radix_tree_root *radix) | |||
235 | /* do the bulk op much less frequently */ | 242 | /* do the bulk op much less frequently */ |
236 | if (run_nr++ % 100) | 243 | if (run_nr++ % 100) |
237 | return 0; | 244 | return 0; |
238 | ret = empty_tree(root, radix, nr); | 245 | ret = empty_tree(trans, root, radix, nr); |
239 | if (ret) | 246 | if (ret) |
240 | return ret; | 247 | return ret; |
241 | ret = fill_tree(root, radix, nr); | 248 | ret = fill_tree(trans, root, radix, nr); |
242 | if (ret) | 249 | if (ret) |
243 | return ret; | 250 | return ret; |
244 | return 0; | 251 | return 0; |
245 | } | 252 | } |
246 | 253 | ||
247 | 254 | ||
248 | int (*ops[])(struct btrfs_root *root, struct radix_tree_root *radix) = | 255 | int (*ops[])(struct btrfs_trans_handle *, |
256 | struct btrfs_root *root, struct radix_tree_root *radix) = | ||
249 | { ins_one, insert_dup, del_one, lookup_item, | 257 | { ins_one, insert_dup, del_one, lookup_item, |
250 | lookup_enoent, bulk_op }; | 258 | lookup_enoent, bulk_op }; |
251 | 259 | ||
@@ -264,7 +272,7 @@ static int fill_radix(struct btrfs_root *root, struct radix_tree_root *radix) | |||
264 | key.objectid = (unsigned long)-1; | 272 | key.objectid = (unsigned long)-1; |
265 | while(1) { | 273 | while(1) { |
266 | btrfs_init_path(&path); | 274 | btrfs_init_path(&path); |
267 | ret = btrfs_search_slot(root, &key, &path, 0, 0); | 275 | ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0); |
268 | if (ret < 0) { | 276 | if (ret < 0) { |
269 | btrfs_release_path(root, &path); | 277 | btrfs_release_path(root, &path); |
270 | return ret; | 278 | return ret; |
@@ -325,6 +333,7 @@ int main(int ac, char **av) | |||
325 | int init_fill_count = 800000; | 333 | int init_fill_count = 800000; |
326 | int err = 0; | 334 | int err = 0; |
327 | int initial_only = 0; | 335 | int initial_only = 0; |
336 | struct btrfs_trans_handle *trans; | ||
328 | radix_tree_init(); | 337 | radix_tree_init(); |
329 | root = open_ctree("dbfile", &super); | 338 | root = open_ctree("dbfile", &super); |
330 | fill_radix(root, &radix); | 339 | fill_radix(root, &radix); |
@@ -346,7 +355,8 @@ int main(int ac, char **av) | |||
346 | } | 355 | } |
347 | } | 356 | } |
348 | printf("initial fill\n"); | 357 | printf("initial fill\n"); |
349 | ret = fill_tree(root, &radix, init_fill_count); | 358 | trans = btrfs_start_transaction(root, 1); |
359 | ret = fill_tree(trans, root, &radix, init_fill_count); | ||
350 | printf("starting run\n"); | 360 | printf("starting run\n"); |
351 | if (ret) { | 361 | if (ret) { |
352 | err = ret; | 362 | err = ret; |
@@ -370,7 +380,7 @@ int main(int ac, char **av) | |||
370 | root = open_ctree("dbfile", &super); | 380 | root = open_ctree("dbfile", &super); |
371 | } | 381 | } |
372 | while(count--) { | 382 | while(count--) { |
373 | ret = ops[op](root, &radix); | 383 | ret = ops[op](trans, root, &radix); |
374 | if (ret) { | 384 | if (ret) { |
375 | fprintf(stderr, "op %d failed %d:%d\n", | 385 | fprintf(stderr, "op %d failed %d:%d\n", |
376 | op, i, iterations); | 386 | op, i, iterations); |
diff --git a/fs/btrfs/root-tree.c b/fs/btrfs/root-tree.c index a24b47274037..9cccecc0f431 100644 --- a/fs/btrfs/root-tree.c +++ b/fs/btrfs/root-tree.c | |||
@@ -20,7 +20,7 @@ int btrfs_find_last_root(struct btrfs_root *root, u64 objectid, | |||
20 | search_key.offset = (u32)-1; | 20 | search_key.offset = (u32)-1; |
21 | 21 | ||
22 | btrfs_init_path(&path); | 22 | btrfs_init_path(&path); |
23 | ret = btrfs_search_slot(root, &search_key, &path, 0, 0); | 23 | ret = btrfs_search_slot(NULL, root, &search_key, &path, 0, 0); |
24 | if (ret < 0) | 24 | if (ret < 0) |
25 | goto out; | 25 | goto out; |
26 | BUG_ON(ret == 0); | 26 | BUG_ON(ret == 0); |
@@ -40,8 +40,9 @@ out: | |||
40 | return ret; | 40 | return ret; |
41 | } | 41 | } |
42 | 42 | ||
43 | int btrfs_update_root(struct btrfs_root *root, struct btrfs_key *key, | 43 | int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root |
44 | struct btrfs_root_item *item) | 44 | *root, struct btrfs_key *key, struct btrfs_root_item |
45 | *item) | ||
45 | { | 46 | { |
46 | struct btrfs_path path; | 47 | struct btrfs_path path; |
47 | struct btrfs_leaf *l; | 48 | struct btrfs_leaf *l; |
@@ -49,7 +50,7 @@ int btrfs_update_root(struct btrfs_root *root, struct btrfs_key *key, | |||
49 | int slot; | 50 | int slot; |
50 | 51 | ||
51 | btrfs_init_path(&path); | 52 | btrfs_init_path(&path); |
52 | ret = btrfs_search_slot(root, key, &path, 0, 1); | 53 | ret = btrfs_search_slot(trans, root, key, &path, 0, 1); |
53 | if (ret < 0) | 54 | if (ret < 0) |
54 | goto out; | 55 | goto out; |
55 | BUG_ON(ret != 0); | 56 | BUG_ON(ret != 0); |
@@ -62,26 +63,28 @@ out: | |||
62 | return ret; | 63 | return ret; |
63 | } | 64 | } |
64 | 65 | ||
65 | int btrfs_insert_root(struct btrfs_root *root, struct btrfs_key *key, | 66 | int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root |
66 | struct btrfs_root_item *item) | 67 | *root, struct btrfs_key *key, struct btrfs_root_item |
68 | *item) | ||
67 | { | 69 | { |
68 | int ret; | 70 | int ret; |
69 | ret = btrfs_insert_item(root, key, item, sizeof(*item)); | 71 | ret = btrfs_insert_item(trans, root, key, item, sizeof(*item)); |
70 | BUG_ON(ret); | 72 | BUG_ON(ret); |
71 | return ret; | 73 | return ret; |
72 | } | 74 | } |
73 | 75 | ||
74 | int btrfs_del_root(struct btrfs_root *root, struct btrfs_key *key) | 76 | int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
77 | struct btrfs_key *key) | ||
75 | { | 78 | { |
76 | struct btrfs_path path; | 79 | struct btrfs_path path; |
77 | int ret; | 80 | int ret; |
78 | 81 | ||
79 | btrfs_init_path(&path); | 82 | btrfs_init_path(&path); |
80 | ret = btrfs_search_slot(root, key, &path, -1, 1); | 83 | ret = btrfs_search_slot(trans, root, key, &path, -1, 1); |
81 | if (ret < 0) | 84 | if (ret < 0) |
82 | goto out; | 85 | goto out; |
83 | BUG_ON(ret != 0); | 86 | BUG_ON(ret != 0); |
84 | ret = btrfs_del_item(root, &path); | 87 | ret = btrfs_del_item(trans, root, &path); |
85 | out: | 88 | out: |
86 | btrfs_release_path(root, &path); | 89 | btrfs_release_path(root, &path); |
87 | return ret; | 90 | return ret; |
diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h new file mode 100644 index 000000000000..3adb6e69fe43 --- /dev/null +++ b/fs/btrfs/transaction.h | |||
@@ -0,0 +1,27 @@ | |||
1 | #ifndef __TRANSACTION__ | ||
2 | #define __TRANSACTION__ | ||
3 | |||
4 | struct btrfs_trans_handle { | ||
5 | u64 transid; | ||
6 | unsigned long blocks_reserved; | ||
7 | unsigned long blocks_used; | ||
8 | }; | ||
9 | |||
10 | static inline struct btrfs_trans_handle * | ||
11 | btrfs_start_transaction(struct btrfs_root *root, int num_blocks) | ||
12 | { | ||
13 | struct btrfs_trans_handle *h = malloc(sizeof(*h)); | ||
14 | h->transid = root->root_key.offset; | ||
15 | h->blocks_reserved = num_blocks; | ||
16 | h->blocks_used = 0; | ||
17 | return h; | ||
18 | } | ||
19 | |||
20 | static inline void btrfs_free_transaction(struct btrfs_root *root, | ||
21 | struct btrfs_trans_handle *handle) | ||
22 | { | ||
23 | memset(handle, 0, sizeof(*handle)); | ||
24 | free(handle); | ||
25 | } | ||
26 | |||
27 | #endif | ||