aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-03-16 16:20:31 -0400
committerDavid Woodhouse <dwmw2@hera.kernel.org>2007-03-16 16:20:31 -0400
commite089f05c18ab36ed5fa7e2319052e03ab800d518 (patch)
treef20d727233bb23fa5a37fc050cf0cc5c9d5e7b48 /fs/btrfs
parent88fd146c27da0f34c512f47e2b3776a0762ecd81 (diff)
Btrfs: transaction handles everywhere
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/Makefile4
-rw-r--r--fs/btrfs/TODO2
-rw-r--r--fs/btrfs/ctree.c204
-rw-r--r--fs/btrfs/ctree.h63
-rw-r--r--fs/btrfs/debug-tree.c1
-rw-r--r--fs/btrfs/dir-item.c20
-rw-r--r--fs/btrfs/dir-test.c70
-rw-r--r--fs/btrfs/disk-io.c60
-rw-r--r--fs/btrfs/disk-io.h16
-rw-r--r--fs/btrfs/extent-tree.c135
-rw-r--r--fs/btrfs/inode-item.c15
-rw-r--r--fs/btrfs/print-tree.h4
-rw-r--r--fs/btrfs/quick-test.c23
-rw-r--r--fs/btrfs/random-test.c62
-rw-r--r--fs/btrfs/root-tree.c23
-rw-r--r--fs/btrfs/transaction.h27
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 @@
1CC=gcc 1CC=gcc
2CFLAGS = -g -Wall 2CFLAGS = -g -Wall -Werror
3headers = radix-tree.h ctree.h disk-io.h kerncompat.h print-tree.h list.h 3headers = radix-tree.h ctree.h disk-io.h kerncompat.h print-tree.h list.h
4objects = ctree.o disk-io.o radix-tree.o mkfs.o extent-tree.o print-tree.o \ 4objects = 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
17all: tester debug-tree quick-test dir-test 17all: tester debug-tree quick-test dir-test tags
18 18
19debug-tree: $(objects) debug-tree.o 19debug-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
9static int split_node(struct btrfs_root *root, struct btrfs_path *path, 9static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root
10 int level); 10 *root, struct btrfs_path *path, int level);
11static int split_leaf(struct btrfs_root *root, struct btrfs_path *path, 11static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
12 int data_size); 12 *root, struct btrfs_path *path, int data_size);
13static int push_node_left(struct btrfs_root *root, struct btrfs_buffer *dst, 13static 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
15static int balance_node_right(struct btrfs_root *root, 15 *src);
16 struct btrfs_buffer *dst_buf, 16static 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);
18static int del_ptr(struct btrfs_root *root, struct btrfs_path *path, int level, 19static 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
21inline void btrfs_init_path(struct btrfs_path *p) 22inline 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
37static int btrfs_cow_block(struct btrfs_root *root, 38static 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
269static int balance_level(struct btrfs_root *root, struct btrfs_path *path, 269static 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 */
441int btrfs_search_slot(struct btrfs_root *root, struct btrfs_key *key, 442int 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 */
522static int fixup_low_keys(struct btrfs_root *root, 526static 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 */
549static int push_node_left(struct btrfs_root *root, struct btrfs_buffer *dst_buf, 553static 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 */
592static int balance_node_right(struct btrfs_root *root, 597static 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 */
638static int insert_new_root(struct btrfs_root *root, 643static 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 */
682static int insert_ptr(struct btrfs_root *root, 687static 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 */
716static int split_node(struct btrfs_root *root, struct btrfs_path *path, 721static 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 */
793static int push_leaf_right(struct btrfs_root *root, struct btrfs_path *path, 798static 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 */
900static int push_leaf_left(struct btrfs_root *root, struct btrfs_path *path, 905static 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 */
1024static int split_leaf(struct btrfs_root *root, struct btrfs_path *path, 1029static 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 */
1125int btrfs_insert_empty_item(struct btrfs_root *root, struct btrfs_path *path, 1130int 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 */
1210int btrfs_insert_item(struct btrfs_root *root, struct btrfs_key *cpu_key, 1216int 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 */
1234static int del_ptr(struct btrfs_root *root, struct btrfs_path *path, int level, 1241static 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 */
1269int btrfs_del_item(struct btrfs_root *root, struct btrfs_path *path) 1276int 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
7struct 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
659struct btrfs_buffer *btrfs_alloc_free_block(struct btrfs_root *root); 662struct btrfs_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
660int btrfs_inc_ref(struct btrfs_root *root, struct btrfs_buffer *buf); 663 struct btrfs_root *root);
661int btrfs_free_extent(struct btrfs_root *root, u64 blocknr, u64 num_blocks, 664int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
662 int pin); 665 struct btrfs_buffer *buf);
663int btrfs_search_slot(struct btrfs_root *root, struct btrfs_key *key, 666int 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);
668int 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);
665void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p); 671void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p);
666void btrfs_init_path(struct btrfs_path *p); 672void btrfs_init_path(struct btrfs_path *p);
667int btrfs_del_item(struct btrfs_root *root, struct btrfs_path *path); 673int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root,
668int btrfs_insert_item(struct btrfs_root *root, struct btrfs_key *key, 674 struct btrfs_path *path);
669 void *data, u32 data_size); 675int btrfs_insert_item(struct btrfs_trans_handle *trans, struct btrfs_root
670int 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); 677int 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);
672int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path); 680int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path);
673int btrfs_leaf_free_space(struct btrfs_root *root, struct btrfs_leaf *leaf); 681int btrfs_leaf_free_space(struct btrfs_root *root, struct btrfs_leaf *leaf);
674int btrfs_drop_snapshot(struct btrfs_root *root, struct btrfs_buffer *snap); 682int btrfs_drop_snapshot(struct btrfs_trans_handle *trans, struct btrfs_root
675int btrfs_finish_extent_commit(struct btrfs_root *root); 683 *root, struct btrfs_buffer *snap);
676int btrfs_del_root(struct btrfs_root *root, struct btrfs_key *key); 684int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct
677int btrfs_insert_root(struct btrfs_root *root, struct btrfs_key *key, 685 btrfs_root *root);
678 struct btrfs_root_item *item); 686int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root,
679int btrfs_update_root(struct btrfs_root *root, struct btrfs_key *key, 687 struct btrfs_key *key);
680 struct btrfs_root_item *item); 688int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root
681int 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);
683int btrfs_insert_dir_item(struct btrfs_root *root, char *name, int name_len, 691int 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
685int btrfs_lookup_dir_item(struct btrfs_root *root, struct btrfs_path *path, 693 *item);
686 u64 dir, char *name, int name_len, int mod); 694int btrfs_find_last_root(struct btrfs_root *root, u64 objectid, struct
695 btrfs_root_item *item, struct btrfs_key *key);
696int 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);
699int 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);
687int btrfs_match_dir_item_name(struct btrfs_root *root, struct btrfs_path *path, 702int 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
9int main(int ac, char **av) { 10int 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
9int btrfs_insert_dir_item(struct btrfs_root *root, char *name, int name_len, 10int 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
43int btrfs_lookup_dir_item(struct btrfs_root *root, struct btrfs_path *path, 45int 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
60int btrfs_match_dir_item_name(struct btrfs_root *root, struct btrfs_path *path, 63int 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
12int keep_running = 1; 13int keep_running = 1;
13struct btrfs_super_block super; 14struct btrfs_super_block super;
@@ -38,7 +39,8 @@ again:
38 return 0; 39 return 0;
39} 40}
40 41
41static int ins_one(struct btrfs_root *root, struct radix_tree_root *radix) 42static 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
99static int insert_dup(struct btrfs_root *root, struct radix_tree_root *radix) 102static 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
119static int del_one(struct btrfs_root *root, struct radix_tree_root *radix) 123static 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
152static int lookup_item(struct btrfs_root *root, struct radix_tree_root *radix) 158static 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
173static int lookup_enoent(struct btrfs_root *root, struct radix_tree_root *radix) 181static 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
194static int empty_tree(struct btrfs_root *root, struct radix_tree_root *radix, 204static 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
255static int fill_tree(struct btrfs_root *root, struct radix_tree_root *radix, 265static 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
283static int bulk_op(struct btrfs_root *root, struct radix_tree_root *radix) 293static 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
302int (*ops[])(struct btrfs_root *root, struct radix_tree_root *radix) = 313int (*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
13static int allocated_blocks = 0; 14static int allocated_blocks = 0;
14int cache_max = 10000; 15int 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
110int dirty_tree_block(struct btrfs_root *root, struct btrfs_buffer *buf) 111int 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
119int clean_tree_block(struct btrfs_root *root, struct btrfs_buffer *buf) 121int 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
128int write_tree_block(struct btrfs_root *root, struct btrfs_buffer *buf) 131int 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
142static int __commit_transaction(struct btrfs_root *root) 146static 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
158static int commit_extent_and_tree_roots(struct btrfs_root *tree_root, 163static 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
180int btrfs_commit_transaction(struct btrfs_root *root, 186int 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
315int write_ctree_super(struct btrfs_root *root, struct btrfs_super_block *s) 322int 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)
338int close_ctree(struct btrfs_root *root, struct btrfs_super_block *s) 346int 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
16struct btrfs_buffer *read_tree_block(struct btrfs_root *root, u64 blocknr); 16struct btrfs_buffer *read_tree_block(struct btrfs_root *root, u64 blocknr);
17struct btrfs_buffer *find_tree_block(struct btrfs_root *root, u64 blocknr); 17struct btrfs_buffer *find_tree_block(struct btrfs_root *root, u64 blocknr);
18int write_tree_block(struct btrfs_root *root, struct btrfs_buffer *buf); 18int write_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root,
19int dirty_tree_block(struct btrfs_root *root, struct btrfs_buffer *buf); 19 struct btrfs_buffer *buf);
20int clean_tree_block(struct btrfs_root *root, struct btrfs_buffer *buf); 20int dirty_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root,
21int btrfs_commit_transaction(struct btrfs_root *root, 21 struct btrfs_buffer *buf);
22 struct btrfs_super_block *s); 22int clean_tree_block(struct btrfs_trans_handle *trans,
23 struct btrfs_root *root, struct btrfs_buffer *buf);
24int btrfs_commit_transaction(struct btrfs_trans_handle *trans, struct btrfs_root
25 *root, struct btrfs_super_block *s);
23struct btrfs_root *open_ctree(char *filename, struct btrfs_super_block *s); 26struct btrfs_root *open_ctree(char *filename, struct btrfs_super_block *s);
24int close_ctree(struct btrfs_root *root, struct btrfs_super_block *s); 27int close_ctree(struct btrfs_root *root, struct btrfs_super_block *s);
25void btrfs_block_release(struct btrfs_root *root, struct btrfs_buffer *buf); 28void btrfs_block_release(struct btrfs_root *root, struct btrfs_buffer *buf);
26int write_ctree_super(struct btrfs_root *root, struct btrfs_super_block *s); 29int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root *root,
30 struct btrfs_super_block *s);
27int mkfs(int fd, u64 num_blocks, u32 blocksize); 31int 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
9static int find_free_extent(struct btrfs_root *orig_root, u64 num_blocks, 10static 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);
12static int finish_current_insert(struct btrfs_root *extent_root); 13static int finish_current_insert(struct btrfs_trans_handle *trans, struct
13static int run_pending(struct btrfs_root *extent_root); 14 btrfs_root *extent_root);
15static 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
24static int inc_block_ref(struct btrfs_root *root, u64 blocknr) 27static 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
56static int lookup_block_ref(struct btrfs_root *root, u64 blocknr, u32 *refs) 60static 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
78int btrfs_inc_ref(struct btrfs_root *root, struct btrfs_buffer *buf) 83int 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
95int btrfs_finish_extent_commit(struct btrfs_root *root) 101int 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
119static int finish_current_insert(struct btrfs_root *extent_root) 126static 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 */
146static int __free_extent(struct btrfs_root *root, u64 blocknr, u64 num_blocks, 154static 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 */
201static int del_pending_extents(struct btrfs_root *extent_root) 209static 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
226static int run_pending(struct btrfs_root *extent_root) 235static 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 */
238int btrfs_free_extent(struct btrfs_root *root, u64 blocknr, u64 num_blocks, 248int 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 */
265static int find_free_extent(struct btrfs_root *orig_root, u64 num_blocks, 275static 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 */
370static int alloc_extent(struct btrfs_root *root, u64 num_blocks, 380static 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 */
413struct btrfs_buffer *btrfs_alloc_free_block(struct btrfs_root *root) 423struct 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 */
435static int walk_down_tree(struct btrfs_root *root, 446static 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 }
472out: 484out:
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 */
486static int walk_up_tree(struct btrfs_root *root, struct btrfs_path *path, 499static 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 */
516int btrfs_drop_snapshot(struct btrfs_root *root, struct btrfs_buffer *snap) 530int 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
8int btrfs_insert_inode(struct btrfs_root *root, u64 objectid, 9int 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
25int btrfs_lookup_inode(struct btrfs_root *root, struct btrfs_path *path, 28int 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_
2void btrfs_print_leaf(struct btrfs_root *root, struct btrfs_leaf *l); 3void btrfs_print_leaf(struct btrfs_root *root, struct btrfs_leaf *l);
3void btrfs_print_tree(struct btrfs_root *root, struct btrfs_buffer *t); 4void 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 */
10int next_key(int i, int max_key) { 11int 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
10int keep_running = 1; 11int keep_running = 1;
11struct btrfs_super_block super; 12struct btrfs_super_block super;
@@ -37,7 +38,8 @@ again:
37 return 0; 38 return 0;
38} 39}
39 40
40static int ins_one(struct btrfs_root *root, struct radix_tree_root *radix) 41static 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
65static int insert_dup(struct btrfs_root *root, struct radix_tree_root *radix) 67static 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
84static int del_one(struct btrfs_root *root, struct radix_tree_root *radix) 87static 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
110static int lookup_item(struct btrfs_root *root, struct radix_tree_root *radix) 114static 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
129static int lookup_enoent(struct btrfs_root *root, struct radix_tree_root *radix) 134static 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
148static int empty_tree(struct btrfs_root *root, struct radix_tree_root *radix, 154static 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
201static int fill_tree(struct btrfs_root *root, struct radix_tree_root *radix, 207static 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
229static int bulk_op(struct btrfs_root *root, struct radix_tree_root *radix) 235static 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
248int (*ops[])(struct btrfs_root *root, struct radix_tree_root *radix) = 255int (*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
43int btrfs_update_root(struct btrfs_root *root, struct btrfs_key *key, 43int 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
65int btrfs_insert_root(struct btrfs_root *root, struct btrfs_key *key, 66int 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
74int btrfs_del_root(struct btrfs_root *root, struct btrfs_key *key) 76int 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);
85out: 88out:
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
4struct btrfs_trans_handle {
5 u64 transid;
6 unsigned long blocks_reserved;
7 unsigned long blocks_used;
8};
9
10static inline struct btrfs_trans_handle *
11btrfs_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
20static 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