diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-03-30 14:27:56 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@hera.kernel.org> | 2007-03-30 14:27:56 -0400 |
commit | d6025579531b7ea170ba283b171ff7a6bf7d0e12 (patch) | |
tree | c3b742fda3a6ac8541c06011bb3c26635db99212 | |
parent | 22b0ebda6c63a1ad66b6a9e806bd226a4a03a049 (diff) |
Btrfs: corruption hunt continues
Signed-off-by: Chris Mason <chris.mason@oracle.com>
-rw-r--r-- | fs/btrfs/bit-radix.c | 9 | ||||
-rw-r--r-- | fs/btrfs/ctree.c | 201 | ||||
-rw-r--r-- | fs/btrfs/ctree.h | 32 | ||||
-rw-r--r-- | fs/btrfs/dir-item.c | 6 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 20 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 8 | ||||
-rw-r--r-- | fs/btrfs/file-item.c | 4 | ||||
-rw-r--r-- | fs/btrfs/inode-map.c | 2 | ||||
-rw-r--r-- | fs/btrfs/root-tree.c | 7 | ||||
-rw-r--r-- | fs/btrfs/super.c | 2 | ||||
-rw-r--r-- | fs/btrfs/transaction.c | 1 |
11 files changed, 187 insertions, 105 deletions
diff --git a/fs/btrfs/bit-radix.c b/fs/btrfs/bit-radix.c index 43807cc3cce7..845422368f48 100644 --- a/fs/btrfs/bit-radix.c +++ b/fs/btrfs/bit-radix.c | |||
@@ -16,12 +16,14 @@ int set_radix_bit(struct radix_tree_root *radix, unsigned long bit) | |||
16 | 16 | ||
17 | bits = radix_tree_lookup(radix, slot); | 17 | bits = radix_tree_lookup(radix, slot); |
18 | if (!bits) { | 18 | if (!bits) { |
19 | bits = kmalloc(BIT_ARRAY_BYTES, GFP_NOIO); | 19 | bits = kmalloc(BIT_ARRAY_BYTES, GFP_NOFS); |
20 | if (!bits) | 20 | if (!bits) |
21 | return -ENOMEM; | 21 | return -ENOMEM; |
22 | memset(bits + 1, 0, BIT_ARRAY_BYTES - sizeof(unsigned long)); | 22 | memset(bits + 1, 0, BIT_ARRAY_BYTES - sizeof(unsigned long)); |
23 | bits[0] = slot; | 23 | bits[0] = slot; |
24 | radix_tree_preload(GFP_NOFS); | ||
24 | ret = radix_tree_insert(radix, slot, bits); | 25 | ret = radix_tree_insert(radix, slot, bits); |
26 | radix_tree_preload_end(); | ||
25 | if (ret) | 27 | if (ret) |
26 | return ret; | 28 | return ret; |
27 | } | 29 | } |
@@ -59,7 +61,7 @@ int clear_radix_bit(struct radix_tree_root *radix, unsigned long bit) | |||
59 | if (!bits) | 61 | if (!bits) |
60 | return 0; | 62 | return 0; |
61 | clear_bit(bit_slot, bits + 1); | 63 | clear_bit(bit_slot, bits + 1); |
62 | 64 | #if 0 | |
63 | for (i = 1; i < BIT_ARRAY_BYTES / sizeof(unsigned long); i++) { | 65 | for (i = 1; i < BIT_ARRAY_BYTES / sizeof(unsigned long); i++) { |
64 | if (bits[i]) { | 66 | if (bits[i]) { |
65 | empty = 0; | 67 | empty = 0; |
@@ -69,8 +71,11 @@ int clear_radix_bit(struct radix_tree_root *radix, unsigned long bit) | |||
69 | 71 | ||
70 | if (empty) { | 72 | if (empty) { |
71 | bits = radix_tree_delete(radix, slot); | 73 | bits = radix_tree_delete(radix, slot); |
74 | synchronize_rcu(); | ||
72 | BUG_ON(!bits); | 75 | BUG_ON(!bits); |
76 | kfree(bits); | ||
73 | } | 77 | } |
78 | #endif | ||
74 | return 0; | 79 | return 0; |
75 | } | 80 | } |
76 | 81 | ||
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index b7f3fcb72c62..a0dfa2d6cb9b 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
@@ -51,7 +51,7 @@ static int btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root | |||
51 | btrfs_set_header_blocknr(&cow_node->header, cow->b_blocknr); | 51 | btrfs_set_header_blocknr(&cow_node->header, cow->b_blocknr); |
52 | btrfs_set_header_generation(&cow_node->header, trans->transid); | 52 | btrfs_set_header_generation(&cow_node->header, trans->transid); |
53 | *cow_ret = cow; | 53 | *cow_ret = cow; |
54 | mark_buffer_dirty(cow); | 54 | btrfs_mark_buffer_dirty(cow); |
55 | btrfs_inc_ref(trans, root, buf); | 55 | btrfs_inc_ref(trans, root, buf); |
56 | if (buf == root->node) { | 56 | if (buf == root->node) { |
57 | root->node = cow; | 57 | root->node = cow; |
@@ -62,7 +62,7 @@ static int btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root | |||
62 | } else { | 62 | } else { |
63 | btrfs_set_node_blockptr(btrfs_buffer_node(parent), parent_slot, | 63 | btrfs_set_node_blockptr(btrfs_buffer_node(parent), parent_slot, |
64 | cow->b_blocknr); | 64 | cow->b_blocknr); |
65 | mark_buffer_dirty(parent); | 65 | btrfs_mark_buffer_dirty(parent); |
66 | btrfs_free_extent(trans, root, buf->b_blocknr, 1, 1); | 66 | btrfs_free_extent(trans, root, buf->b_blocknr, 1, 1); |
67 | } | 67 | } |
68 | btrfs_block_release(root, buf); | 68 | btrfs_block_release(root, buf); |
@@ -312,11 +312,12 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root | |||
312 | BUG_ON(!child); | 312 | BUG_ON(!child); |
313 | root->node = child; | 313 | root->node = child; |
314 | path->nodes[level] = NULL; | 314 | path->nodes[level] = NULL; |
315 | clean_tree_block(trans, root, mid_buf); | ||
316 | wait_on_buffer(mid_buf); | ||
315 | /* once for the path */ | 317 | /* once for the path */ |
316 | btrfs_block_release(root, mid_buf); | 318 | btrfs_block_release(root, mid_buf); |
317 | /* once for the root ptr */ | 319 | /* once for the root ptr */ |
318 | btrfs_block_release(root, mid_buf); | 320 | btrfs_block_release(root, mid_buf); |
319 | clean_tree_block(trans, root, mid_buf); | ||
320 | return btrfs_free_extent(trans, root, blocknr, 1, 1); | 321 | return btrfs_free_extent(trans, root, blocknr, 1, 1); |
321 | } | 322 | } |
322 | parent = btrfs_buffer_node(parent_buf); | 323 | parent = btrfs_buffer_node(parent_buf); |
@@ -351,8 +352,9 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root | |||
351 | ret = wret; | 352 | ret = wret; |
352 | if (btrfs_header_nritems(&right->header) == 0) { | 353 | if (btrfs_header_nritems(&right->header) == 0) { |
353 | u64 blocknr = right_buf->b_blocknr; | 354 | u64 blocknr = right_buf->b_blocknr; |
354 | btrfs_block_release(root, right_buf); | ||
355 | clean_tree_block(trans, root, right_buf); | 355 | clean_tree_block(trans, root, right_buf); |
356 | wait_on_buffer(right_buf); | ||
357 | btrfs_block_release(root, right_buf); | ||
356 | right_buf = NULL; | 358 | right_buf = NULL; |
357 | right = NULL; | 359 | right = NULL; |
358 | wret = del_ptr(trans, root, path, level + 1, pslot + | 360 | wret = del_ptr(trans, root, path, level + 1, pslot + |
@@ -363,10 +365,11 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root | |||
363 | if (wret) | 365 | if (wret) |
364 | ret = wret; | 366 | ret = wret; |
365 | } else { | 367 | } else { |
366 | memcpy(&parent->ptrs[pslot + 1].key, | 368 | btrfs_memcpy(root, parent, |
367 | &right->ptrs[0].key, | 369 | &parent->ptrs[pslot + 1].key, |
368 | sizeof(struct btrfs_disk_key)); | 370 | &right->ptrs[0].key, |
369 | mark_buffer_dirty(parent_buf); | 371 | sizeof(struct btrfs_disk_key)); |
372 | btrfs_mark_buffer_dirty(parent_buf); | ||
370 | } | 373 | } |
371 | } | 374 | } |
372 | if (btrfs_header_nritems(&mid->header) == 1) { | 375 | if (btrfs_header_nritems(&mid->header) == 1) { |
@@ -388,8 +391,9 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root | |||
388 | if (btrfs_header_nritems(&mid->header) == 0) { | 391 | if (btrfs_header_nritems(&mid->header) == 0) { |
389 | /* we've managed to empty the middle node, drop it */ | 392 | /* we've managed to empty the middle node, drop it */ |
390 | u64 blocknr = mid_buf->b_blocknr; | 393 | u64 blocknr = mid_buf->b_blocknr; |
391 | btrfs_block_release(root, mid_buf); | ||
392 | clean_tree_block(trans, root, mid_buf); | 394 | clean_tree_block(trans, root, mid_buf); |
395 | wait_on_buffer(mid_buf); | ||
396 | btrfs_block_release(root, mid_buf); | ||
393 | mid_buf = NULL; | 397 | mid_buf = NULL; |
394 | mid = NULL; | 398 | mid = NULL; |
395 | wret = del_ptr(trans, root, path, level + 1, pslot); | 399 | wret = del_ptr(trans, root, path, level + 1, pslot); |
@@ -400,9 +404,10 @@ static int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root | |||
400 | ret = wret; | 404 | ret = wret; |
401 | } else { | 405 | } else { |
402 | /* update the parent key to reflect our changes */ | 406 | /* update the parent key to reflect our changes */ |
403 | memcpy(&parent->ptrs[pslot].key, &mid->ptrs[0].key, | 407 | btrfs_memcpy(root, parent, |
404 | sizeof(struct btrfs_disk_key)); | 408 | &parent->ptrs[pslot].key, &mid->ptrs[0].key, |
405 | mark_buffer_dirty(parent_buf); | 409 | sizeof(struct btrfs_disk_key)); |
410 | btrfs_mark_buffer_dirty(parent_buf); | ||
406 | } | 411 | } |
407 | 412 | ||
408 | /* update the path */ | 413 | /* update the path */ |
@@ -544,8 +549,8 @@ static int fixup_low_keys(struct btrfs_trans_handle *trans, struct btrfs_root | |||
544 | if (!path->nodes[i]) | 549 | if (!path->nodes[i]) |
545 | break; | 550 | break; |
546 | t = btrfs_buffer_node(path->nodes[i]); | 551 | t = btrfs_buffer_node(path->nodes[i]); |
547 | memcpy(&t->ptrs[tslot].key, key, sizeof(*key)); | 552 | btrfs_memcpy(root, t, &t->ptrs[tslot].key, key, sizeof(*key)); |
548 | mark_buffer_dirty(path->nodes[i]); | 553 | btrfs_mark_buffer_dirty(path->nodes[i]); |
549 | if (tslot != 0) | 554 | if (tslot != 0) |
550 | break; | 555 | break; |
551 | } | 556 | } |
@@ -580,17 +585,17 @@ static int push_node_left(struct btrfs_trans_handle *trans, struct btrfs_root | |||
580 | if (src_nritems < push_items) | 585 | if (src_nritems < push_items) |
581 | push_items = src_nritems; | 586 | push_items = src_nritems; |
582 | 587 | ||
583 | memcpy(dst->ptrs + dst_nritems, src->ptrs, | 588 | btrfs_memcpy(root, dst, dst->ptrs + dst_nritems, src->ptrs, |
584 | push_items * sizeof(struct btrfs_key_ptr)); | 589 | push_items * sizeof(struct btrfs_key_ptr)); |
585 | if (push_items < src_nritems) { | 590 | if (push_items < src_nritems) { |
586 | memmove(src->ptrs, src->ptrs + push_items, | 591 | btrfs_memmove(root, src, src->ptrs, src->ptrs + push_items, |
587 | (src_nritems - push_items) * | 592 | (src_nritems - push_items) * |
588 | sizeof(struct btrfs_key_ptr)); | 593 | sizeof(struct btrfs_key_ptr)); |
589 | } | 594 | } |
590 | btrfs_set_header_nritems(&src->header, src_nritems - push_items); | 595 | btrfs_set_header_nritems(&src->header, src_nritems - push_items); |
591 | btrfs_set_header_nritems(&dst->header, dst_nritems + push_items); | 596 | btrfs_set_header_nritems(&dst->header, dst_nritems + push_items); |
592 | mark_buffer_dirty(src_buf); | 597 | btrfs_mark_buffer_dirty(src_buf); |
593 | mark_buffer_dirty(dst_buf); | 598 | btrfs_mark_buffer_dirty(dst_buf); |
594 | return ret; | 599 | return ret; |
595 | } | 600 | } |
596 | 601 | ||
@@ -629,16 +634,18 @@ static int balance_node_right(struct btrfs_trans_handle *trans, struct | |||
629 | if (max_push < push_items) | 634 | if (max_push < push_items) |
630 | push_items = max_push; | 635 | push_items = max_push; |
631 | 636 | ||
632 | memmove(dst->ptrs + push_items, dst->ptrs, | 637 | btrfs_memmove(root, dst, dst->ptrs + push_items, dst->ptrs, |
633 | dst_nritems * sizeof(struct btrfs_key_ptr)); | 638 | dst_nritems * sizeof(struct btrfs_key_ptr)); |
634 | memcpy(dst->ptrs, src->ptrs + src_nritems - push_items, | 639 | |
635 | push_items * sizeof(struct btrfs_key_ptr)); | 640 | btrfs_memcpy(root, dst, dst->ptrs, |
641 | src->ptrs + src_nritems - push_items, | ||
642 | push_items * sizeof(struct btrfs_key_ptr)); | ||
636 | 643 | ||
637 | btrfs_set_header_nritems(&src->header, src_nritems - push_items); | 644 | btrfs_set_header_nritems(&src->header, src_nritems - push_items); |
638 | btrfs_set_header_nritems(&dst->header, dst_nritems + push_items); | 645 | btrfs_set_header_nritems(&dst->header, dst_nritems + push_items); |
639 | 646 | ||
640 | mark_buffer_dirty(src_buf); | 647 | btrfs_mark_buffer_dirty(src_buf); |
641 | mark_buffer_dirty(dst_buf); | 648 | btrfs_mark_buffer_dirty(dst_buf); |
642 | return ret; | 649 | return ret; |
643 | } | 650 | } |
644 | 651 | ||
@@ -674,10 +681,11 @@ static int insert_new_root(struct btrfs_trans_handle *trans, struct btrfs_root | |||
674 | lower_key = &((struct btrfs_leaf *)lower)->items[0].key; | 681 | lower_key = &((struct btrfs_leaf *)lower)->items[0].key; |
675 | else | 682 | else |
676 | lower_key = &lower->ptrs[0].key; | 683 | lower_key = &lower->ptrs[0].key; |
677 | memcpy(&c->ptrs[0].key, lower_key, sizeof(struct btrfs_disk_key)); | 684 | btrfs_memcpy(root, c, &c->ptrs[0].key, lower_key, |
685 | sizeof(struct btrfs_disk_key)); | ||
678 | btrfs_set_node_blockptr(c, 0, path->nodes[level - 1]->b_blocknr); | 686 | btrfs_set_node_blockptr(c, 0, path->nodes[level - 1]->b_blocknr); |
679 | 687 | ||
680 | mark_buffer_dirty(t); | 688 | btrfs_mark_buffer_dirty(t); |
681 | 689 | ||
682 | /* the super has an extra ref to root->node */ | 690 | /* the super has an extra ref to root->node */ |
683 | btrfs_block_release(root, root->node); | 691 | btrfs_block_release(root, root->node); |
@@ -712,13 +720,15 @@ static int insert_ptr(struct btrfs_trans_handle *trans, struct btrfs_root | |||
712 | if (nritems == BTRFS_NODEPTRS_PER_BLOCK(root)) | 720 | if (nritems == BTRFS_NODEPTRS_PER_BLOCK(root)) |
713 | BUG(); | 721 | BUG(); |
714 | if (slot != nritems) { | 722 | if (slot != nritems) { |
715 | memmove(lower->ptrs + slot + 1, lower->ptrs + slot, | 723 | btrfs_memmove(root, lower, lower->ptrs + slot + 1, |
716 | (nritems - slot) * sizeof(struct btrfs_key_ptr)); | 724 | lower->ptrs + slot, |
725 | (nritems - slot) * sizeof(struct btrfs_key_ptr)); | ||
717 | } | 726 | } |
718 | memcpy(&lower->ptrs[slot].key, key, sizeof(struct btrfs_disk_key)); | 727 | btrfs_memcpy(root, lower, &lower->ptrs[slot].key, |
728 | key, sizeof(struct btrfs_disk_key)); | ||
719 | btrfs_set_node_blockptr(lower, slot, blocknr); | 729 | btrfs_set_node_blockptr(lower, slot, blocknr); |
720 | btrfs_set_header_nritems(&lower->header, nritems + 1); | 730 | btrfs_set_header_nritems(&lower->header, nritems + 1); |
721 | mark_buffer_dirty(path->nodes[level]); | 731 | btrfs_mark_buffer_dirty(path->nodes[level]); |
722 | return 0; | 732 | return 0; |
723 | } | 733 | } |
724 | 734 | ||
@@ -761,14 +771,14 @@ static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root | |||
761 | btrfs_set_header_parentid(&split->header, | 771 | btrfs_set_header_parentid(&split->header, |
762 | btrfs_header_parentid(btrfs_buffer_header(root->node))); | 772 | btrfs_header_parentid(btrfs_buffer_header(root->node))); |
763 | mid = (c_nritems + 1) / 2; | 773 | mid = (c_nritems + 1) / 2; |
764 | memcpy(split->ptrs, c->ptrs + mid, | 774 | btrfs_memcpy(root, split, split->ptrs, c->ptrs + mid, |
765 | (c_nritems - mid) * sizeof(struct btrfs_key_ptr)); | 775 | (c_nritems - mid) * sizeof(struct btrfs_key_ptr)); |
766 | btrfs_set_header_nritems(&split->header, c_nritems - mid); | 776 | btrfs_set_header_nritems(&split->header, c_nritems - mid); |
767 | btrfs_set_header_nritems(&c->header, mid); | 777 | btrfs_set_header_nritems(&c->header, mid); |
768 | ret = 0; | 778 | ret = 0; |
769 | 779 | ||
770 | mark_buffer_dirty(t); | 780 | btrfs_mark_buffer_dirty(t); |
771 | mark_buffer_dirty(split_buffer); | 781 | btrfs_mark_buffer_dirty(split_buffer); |
772 | wret = insert_ptr(trans, root, path, &split->ptrs[0].key, | 782 | wret = insert_ptr(trans, root, path, &split->ptrs[0].key, |
773 | split_buffer->b_blocknr, path->slots[level + 1] + 1, | 783 | split_buffer->b_blocknr, path->slots[level + 1] + 1, |
774 | level + 1); | 784 | level + 1); |
@@ -875,17 +885,22 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root | |||
875 | push_space = btrfs_item_end(left->items + left_nritems - push_items); | 885 | push_space = btrfs_item_end(left->items + left_nritems - push_items); |
876 | push_space -= leaf_data_end(root, left); | 886 | push_space -= leaf_data_end(root, left); |
877 | /* make room in the right data area */ | 887 | /* make room in the right data area */ |
878 | memmove(btrfs_leaf_data(right) + leaf_data_end(root, right) - | 888 | btrfs_memmove(root, right, btrfs_leaf_data(right) + |
879 | push_space, btrfs_leaf_data(right) + leaf_data_end(root, right), | 889 | leaf_data_end(root, right) - push_space, |
880 | BTRFS_LEAF_DATA_SIZE(root) - leaf_data_end(root, right)); | 890 | btrfs_leaf_data(right) + |
891 | leaf_data_end(root, right), BTRFS_LEAF_DATA_SIZE(root) - | ||
892 | leaf_data_end(root, right)); | ||
881 | /* copy from the left data area */ | 893 | /* copy from the left data area */ |
882 | memcpy(btrfs_leaf_data(right) + BTRFS_LEAF_DATA_SIZE(root) - push_space, | 894 | btrfs_memcpy(root, right, btrfs_leaf_data(right) + |
883 | btrfs_leaf_data(left) + leaf_data_end(root, left), push_space); | 895 | BTRFS_LEAF_DATA_SIZE(root) - push_space, |
884 | memmove(right->items + push_items, right->items, | 896 | btrfs_leaf_data(left) + leaf_data_end(root, left), |
897 | push_space); | ||
898 | btrfs_memmove(root, right, right->items + push_items, right->items, | ||
885 | right_nritems * sizeof(struct btrfs_item)); | 899 | right_nritems * sizeof(struct btrfs_item)); |
886 | /* copy the items from left to right */ | 900 | /* copy the items from left to right */ |
887 | memcpy(right->items, left->items + left_nritems - push_items, | 901 | btrfs_memcpy(root, right, right->items, left->items + |
888 | push_items * sizeof(struct btrfs_item)); | 902 | left_nritems - push_items, |
903 | push_items * sizeof(struct btrfs_item)); | ||
889 | 904 | ||
890 | /* update the item pointers */ | 905 | /* update the item pointers */ |
891 | right_nritems += push_items; | 906 | right_nritems += push_items; |
@@ -899,11 +914,11 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root | |||
899 | left_nritems -= push_items; | 914 | left_nritems -= push_items; |
900 | btrfs_set_header_nritems(&left->header, left_nritems); | 915 | btrfs_set_header_nritems(&left->header, left_nritems); |
901 | 916 | ||
902 | mark_buffer_dirty(left_buf); | 917 | btrfs_mark_buffer_dirty(left_buf); |
903 | mark_buffer_dirty(right_buf); | 918 | btrfs_mark_buffer_dirty(right_buf); |
904 | memcpy(&upper_node->ptrs[slot + 1].key, | 919 | btrfs_memcpy(root, upper_node, &upper_node->ptrs[slot + 1].key, |
905 | &right->items[0].key, sizeof(struct btrfs_disk_key)); | 920 | &right->items[0].key, sizeof(struct btrfs_disk_key)); |
906 | mark_buffer_dirty(upper); | 921 | btrfs_mark_buffer_dirty(upper); |
907 | 922 | ||
908 | /* then fixup the leaf pointer in the path */ | 923 | /* then fixup the leaf pointer in the path */ |
909 | if (path->slots[0] >= left_nritems) { | 924 | if (path->slots[0] >= left_nritems) { |
@@ -977,14 +992,16 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root | |||
977 | return 1; | 992 | return 1; |
978 | } | 993 | } |
979 | /* push data from right to left */ | 994 | /* push data from right to left */ |
980 | memcpy(left->items + btrfs_header_nritems(&left->header), | 995 | btrfs_memcpy(root, left, left->items + |
981 | right->items, push_items * sizeof(struct btrfs_item)); | 996 | btrfs_header_nritems(&left->header), |
997 | right->items, push_items * sizeof(struct btrfs_item)); | ||
982 | push_space = BTRFS_LEAF_DATA_SIZE(root) - | 998 | push_space = BTRFS_LEAF_DATA_SIZE(root) - |
983 | btrfs_item_offset(right->items + push_items -1); | 999 | btrfs_item_offset(right->items + push_items -1); |
984 | memcpy(btrfs_leaf_data(left) + leaf_data_end(root, left) - push_space, | 1000 | btrfs_memcpy(root, left, btrfs_leaf_data(left) + |
985 | btrfs_leaf_data(right) + | 1001 | leaf_data_end(root, left) - push_space, |
986 | btrfs_item_offset(right->items + push_items - 1), | 1002 | btrfs_leaf_data(right) + |
987 | push_space); | 1003 | btrfs_item_offset(right->items + push_items - 1), |
1004 | push_space); | ||
988 | old_left_nritems = btrfs_header_nritems(&left->header); | 1005 | old_left_nritems = btrfs_header_nritems(&left->header); |
989 | BUG_ON(old_left_nritems < 0); | 1006 | BUG_ON(old_left_nritems < 0); |
990 | 1007 | ||
@@ -1000,10 +1017,11 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1000 | /* fixup right node */ | 1017 | /* fixup right node */ |
1001 | push_space = btrfs_item_offset(right->items + push_items - 1) - | 1018 | push_space = btrfs_item_offset(right->items + push_items - 1) - |
1002 | leaf_data_end(root, right); | 1019 | leaf_data_end(root, right); |
1003 | memmove(btrfs_leaf_data(right) + BTRFS_LEAF_DATA_SIZE(root) - | 1020 | btrfs_memmove(root, right, btrfs_leaf_data(right) + |
1004 | push_space, btrfs_leaf_data(right) + | 1021 | BTRFS_LEAF_DATA_SIZE(root) - push_space, |
1005 | leaf_data_end(root, right), push_space); | 1022 | btrfs_leaf_data(right) + |
1006 | memmove(right->items, right->items + push_items, | 1023 | leaf_data_end(root, right), push_space); |
1024 | btrfs_memmove(root, right, right->items, right->items + push_items, | ||
1007 | (btrfs_header_nritems(&right->header) - push_items) * | 1025 | (btrfs_header_nritems(&right->header) - push_items) * |
1008 | sizeof(struct btrfs_item)); | 1026 | sizeof(struct btrfs_item)); |
1009 | btrfs_set_header_nritems(&right->header, | 1027 | btrfs_set_header_nritems(&right->header, |
@@ -1017,8 +1035,8 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1017 | push_space = btrfs_item_offset(right->items + i); | 1035 | push_space = btrfs_item_offset(right->items + i); |
1018 | } | 1036 | } |
1019 | 1037 | ||
1020 | mark_buffer_dirty(t); | 1038 | btrfs_mark_buffer_dirty(t); |
1021 | mark_buffer_dirty(right_buf); | 1039 | btrfs_mark_buffer_dirty(right_buf); |
1022 | 1040 | ||
1023 | wret = fixup_low_keys(trans, root, path, &right->items[0].key, 1); | 1041 | wret = fixup_low_keys(trans, root, path, &right->items[0].key, 1); |
1024 | if (wret) | 1042 | if (wret) |
@@ -1110,11 +1128,12 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1110 | btrfs_header_parentid(btrfs_buffer_header(root->node))); | 1128 | btrfs_header_parentid(btrfs_buffer_header(root->node))); |
1111 | data_copy_size = btrfs_item_end(l->items + mid) - | 1129 | data_copy_size = btrfs_item_end(l->items + mid) - |
1112 | leaf_data_end(root, l); | 1130 | leaf_data_end(root, l); |
1113 | memcpy(right->items, l->items + mid, | 1131 | btrfs_memcpy(root, right, right->items, l->items + mid, |
1114 | (nritems - mid) * sizeof(struct btrfs_item)); | 1132 | (nritems - mid) * sizeof(struct btrfs_item)); |
1115 | memcpy(btrfs_leaf_data(right) + BTRFS_LEAF_DATA_SIZE(root) - | 1133 | btrfs_memcpy(root, right, |
1116 | data_copy_size, btrfs_leaf_data(l) + | 1134 | btrfs_leaf_data(right) + BTRFS_LEAF_DATA_SIZE(root) - |
1117 | leaf_data_end(root, l), data_copy_size); | 1135 | data_copy_size, btrfs_leaf_data(l) + |
1136 | leaf_data_end(root, l), data_copy_size); | ||
1118 | rt_data_off = BTRFS_LEAF_DATA_SIZE(root) - | 1137 | rt_data_off = BTRFS_LEAF_DATA_SIZE(root) - |
1119 | btrfs_item_end(l->items + mid); | 1138 | btrfs_item_end(l->items + mid); |
1120 | 1139 | ||
@@ -1129,8 +1148,8 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1129 | right_buffer->b_blocknr, path->slots[1] + 1, 1); | 1148 | right_buffer->b_blocknr, path->slots[1] + 1, 1); |
1130 | if (wret) | 1149 | if (wret) |
1131 | ret = wret; | 1150 | ret = wret; |
1132 | mark_buffer_dirty(right_buffer); | 1151 | btrfs_mark_buffer_dirty(right_buffer); |
1133 | mark_buffer_dirty(l_buf); | 1152 | btrfs_mark_buffer_dirty(l_buf); |
1134 | BUG_ON(path->slots[0] != slot); | 1153 | BUG_ON(path->slots[0] != slot); |
1135 | if (mid <= slot) { | 1154 | if (mid <= slot) { |
1136 | btrfs_block_release(root, path->nodes[0]); | 1155 | btrfs_block_release(root, path->nodes[0]); |
@@ -1200,22 +1219,23 @@ int btrfs_insert_empty_item(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1200 | } | 1219 | } |
1201 | 1220 | ||
1202 | /* shift the items */ | 1221 | /* shift the items */ |
1203 | memmove(leaf->items + slot + 1, leaf->items + slot, | 1222 | btrfs_memmove(root, leaf, leaf->items + slot + 1, |
1204 | (nritems - slot) * sizeof(struct btrfs_item)); | 1223 | leaf->items + slot, |
1224 | (nritems - slot) * sizeof(struct btrfs_item)); | ||
1205 | 1225 | ||
1206 | /* shift the data */ | 1226 | /* shift the data */ |
1207 | memmove(btrfs_leaf_data(leaf) + data_end - data_size, | 1227 | btrfs_memmove(root, leaf, btrfs_leaf_data(leaf) + |
1208 | btrfs_leaf_data(leaf) + | 1228 | data_end - data_size, btrfs_leaf_data(leaf) + |
1209 | data_end, old_data - data_end); | 1229 | data_end, old_data - data_end); |
1210 | data_end = old_data; | 1230 | data_end = old_data; |
1211 | } | 1231 | } |
1212 | /* setup the item for the new data */ | 1232 | /* setup the item for the new data */ |
1213 | memcpy(&leaf->items[slot].key, &disk_key, | 1233 | btrfs_memcpy(root, leaf, &leaf->items[slot].key, &disk_key, |
1214 | sizeof(struct btrfs_disk_key)); | 1234 | sizeof(struct btrfs_disk_key)); |
1215 | btrfs_set_item_offset(leaf->items + slot, data_end - data_size); | 1235 | btrfs_set_item_offset(leaf->items + slot, data_end - data_size); |
1216 | btrfs_set_item_size(leaf->items + slot, data_size); | 1236 | btrfs_set_item_size(leaf->items + slot, data_size); |
1217 | btrfs_set_header_nritems(&leaf->header, nritems + 1); | 1237 | btrfs_set_header_nritems(&leaf->header, nritems + 1); |
1218 | mark_buffer_dirty(leaf_buf); | 1238 | btrfs_mark_buffer_dirty(leaf_buf); |
1219 | 1239 | ||
1220 | ret = 0; | 1240 | ret = 0; |
1221 | if (slot == 0) | 1241 | if (slot == 0) |
@@ -1245,8 +1265,9 @@ int btrfs_insert_item(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1245 | if (!ret) { | 1265 | if (!ret) { |
1246 | ptr = btrfs_item_ptr(btrfs_buffer_leaf(path.nodes[0]), | 1266 | ptr = btrfs_item_ptr(btrfs_buffer_leaf(path.nodes[0]), |
1247 | path.slots[0], u8); | 1267 | path.slots[0], u8); |
1248 | memcpy(ptr, data, data_size); | 1268 | btrfs_memcpy(root, path.nodes[0]->b_data, |
1249 | mark_buffer_dirty(path.nodes[0]); | 1269 | ptr, data, data_size); |
1270 | btrfs_mark_buffer_dirty(path.nodes[0]); | ||
1250 | } | 1271 | } |
1251 | btrfs_release_path(root, &path); | 1272 | btrfs_release_path(root, &path); |
1252 | return ret; | 1273 | return ret; |
@@ -1271,8 +1292,10 @@ static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
1271 | node = btrfs_buffer_node(parent); | 1292 | node = btrfs_buffer_node(parent); |
1272 | nritems = btrfs_header_nritems(&node->header); | 1293 | nritems = btrfs_header_nritems(&node->header); |
1273 | if (slot != nritems -1) { | 1294 | if (slot != nritems -1) { |
1274 | memmove(node->ptrs + slot, node->ptrs + slot + 1, | 1295 | btrfs_memmove(root, node, node->ptrs + slot, |
1275 | sizeof(struct btrfs_key_ptr) * (nritems - slot - 1)); | 1296 | node->ptrs + slot + 1, |
1297 | sizeof(struct btrfs_key_ptr) * | ||
1298 | (nritems - slot - 1)); | ||
1276 | } | 1299 | } |
1277 | nritems--; | 1300 | nritems--; |
1278 | btrfs_set_header_nritems(&node->header, nritems); | 1301 | btrfs_set_header_nritems(&node->header, nritems); |
@@ -1287,7 +1310,7 @@ static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
1287 | if (wret) | 1310 | if (wret) |
1288 | ret = wret; | 1311 | ret = wret; |
1289 | } | 1312 | } |
1290 | mark_buffer_dirty(parent); | 1313 | btrfs_mark_buffer_dirty(parent); |
1291 | return ret; | 1314 | return ret; |
1292 | } | 1315 | } |
1293 | 1316 | ||
@@ -1317,16 +1340,18 @@ int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
1317 | if (slot != nritems - 1) { | 1340 | if (slot != nritems - 1) { |
1318 | int i; | 1341 | int i; |
1319 | int data_end = leaf_data_end(root, leaf); | 1342 | int data_end = leaf_data_end(root, leaf); |
1320 | memmove(btrfs_leaf_data(leaf) + data_end + dsize, | 1343 | btrfs_memmove(root, leaf, btrfs_leaf_data(leaf) + |
1321 | btrfs_leaf_data(leaf) + data_end, | 1344 | data_end + dsize, |
1322 | doff - data_end); | 1345 | btrfs_leaf_data(leaf) + data_end, |
1346 | doff - data_end); | ||
1323 | for (i = slot + 1; i < nritems; i++) { | 1347 | for (i = slot + 1; i < nritems; i++) { |
1324 | u32 ioff = btrfs_item_offset(leaf->items + i); | 1348 | u32 ioff = btrfs_item_offset(leaf->items + i); |
1325 | btrfs_set_item_offset(leaf->items + i, ioff + dsize); | 1349 | btrfs_set_item_offset(leaf->items + i, ioff + dsize); |
1326 | } | 1350 | } |
1327 | memmove(leaf->items + slot, leaf->items + slot + 1, | 1351 | btrfs_memmove(root, leaf, leaf->items + slot, |
1328 | sizeof(struct btrfs_item) * | 1352 | leaf->items + slot + 1, |
1329 | (nritems - slot - 1)); | 1353 | sizeof(struct btrfs_item) * |
1354 | (nritems - slot - 1)); | ||
1330 | } | 1355 | } |
1331 | btrfs_set_header_nritems(&leaf->header, nritems - 1); | 1356 | btrfs_set_header_nritems(&leaf->header, nritems - 1); |
1332 | nritems--; | 1357 | nritems--; |
@@ -1336,6 +1361,7 @@ int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
1336 | btrfs_set_header_level(&leaf->header, 0); | 1361 | btrfs_set_header_level(&leaf->header, 0); |
1337 | } else { | 1362 | } else { |
1338 | clean_tree_block(trans, root, leaf_buf); | 1363 | clean_tree_block(trans, root, leaf_buf); |
1364 | wait_on_buffer(leaf_buf); | ||
1339 | wret = del_ptr(trans, root, path, 1, path->slots[1]); | 1365 | wret = del_ptr(trans, root, path, 1, path->slots[1]); |
1340 | if (wret) | 1366 | if (wret) |
1341 | ret = wret; | 1367 | ret = wret; |
@@ -1373,6 +1399,7 @@ int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
1373 | if (btrfs_header_nritems(&leaf->header) == 0) { | 1399 | if (btrfs_header_nritems(&leaf->header) == 0) { |
1374 | u64 blocknr = leaf_buf->b_blocknr; | 1400 | u64 blocknr = leaf_buf->b_blocknr; |
1375 | clean_tree_block(trans, root, leaf_buf); | 1401 | clean_tree_block(trans, root, leaf_buf); |
1402 | wait_on_buffer(leaf_buf); | ||
1376 | wret = del_ptr(trans, root, path, 1, slot); | 1403 | wret = del_ptr(trans, root, path, 1, slot); |
1377 | if (wret) | 1404 | if (wret) |
1378 | ret = wret; | 1405 | ret = wret; |
@@ -1382,11 +1409,11 @@ int btrfs_del_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
1382 | if (wret) | 1409 | if (wret) |
1383 | ret = wret; | 1410 | ret = wret; |
1384 | } else { | 1411 | } else { |
1385 | mark_buffer_dirty(leaf_buf); | 1412 | btrfs_mark_buffer_dirty(leaf_buf); |
1386 | btrfs_block_release(root, leaf_buf); | 1413 | btrfs_block_release(root, leaf_buf); |
1387 | } | 1414 | } |
1388 | } else { | 1415 | } else { |
1389 | mark_buffer_dirty(leaf_buf); | 1416 | btrfs_mark_buffer_dirty(leaf_buf); |
1390 | } | 1417 | } |
1391 | } | 1418 | } |
1392 | return ret; | 1419 | return ret; |
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index df1a025a771c..9ec0d65ebe9b 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -2,6 +2,7 @@ | |||
2 | #define __BTRFS__ | 2 | #define __BTRFS__ |
3 | 3 | ||
4 | #include <linux/fs.h> | 4 | #include <linux/fs.h> |
5 | #include <linux/buffer_head.h> | ||
5 | #include "bit-radix.h" | 6 | #include "bit-radix.h" |
6 | 7 | ||
7 | struct btrfs_trans_handle; | 8 | struct btrfs_trans_handle; |
@@ -834,6 +835,37 @@ static inline struct btrfs_root *btrfs_sb(struct super_block *sb) | |||
834 | return sb->s_fs_info; | 835 | return sb->s_fs_info; |
835 | } | 836 | } |
836 | 837 | ||
838 | static inline void btrfs_check_bounds(void *vptr, size_t len, | ||
839 | void *vcontainer, size_t container_len) | ||
840 | { | ||
841 | char *ptr = vptr; | ||
842 | char *container = vcontainer; | ||
843 | WARN_ON(ptr < container); | ||
844 | WARN_ON(ptr + len > container + container_len); | ||
845 | } | ||
846 | |||
847 | static inline void btrfs_memcpy(struct btrfs_root *root, | ||
848 | void *dst_block, | ||
849 | void *dst, const void *src, size_t nr) | ||
850 | { | ||
851 | btrfs_check_bounds(dst, nr, dst_block, root->fs_info->sb->s_blocksize); | ||
852 | memcpy(dst, src, nr); | ||
853 | } | ||
854 | |||
855 | static inline void btrfs_memmove(struct btrfs_root *root, | ||
856 | void *dst_block, | ||
857 | void *dst, void *src, size_t nr) | ||
858 | { | ||
859 | btrfs_check_bounds(dst, nr, dst_block, root->fs_info->sb->s_blocksize); | ||
860 | memmove(dst, src, nr); | ||
861 | } | ||
862 | |||
863 | static inline void btrfs_mark_buffer_dirty(struct buffer_head *bh) | ||
864 | { | ||
865 | WARN_ON(!atomic_read(&bh->b_count)); | ||
866 | mark_buffer_dirty(bh); | ||
867 | } | ||
868 | |||
837 | /* helper function to cast into the data area of the leaf. */ | 869 | /* helper function to cast into the data area of the leaf. */ |
838 | #define btrfs_item_ptr(leaf, slot, type) \ | 870 | #define btrfs_item_ptr(leaf, slot, type) \ |
839 | ((type *)(btrfs_leaf_data(leaf) + \ | 871 | ((type *)(btrfs_leaf_data(leaf) + \ |
diff --git a/fs/btrfs/dir-item.c b/fs/btrfs/dir-item.c index 18d3e168ad0a..f55c89472ac0 100644 --- a/fs/btrfs/dir-item.c +++ b/fs/btrfs/dir-item.c | |||
@@ -34,10 +34,8 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root | |||
34 | btrfs_set_dir_flags(dir_item, 0); | 34 | btrfs_set_dir_flags(dir_item, 0); |
35 | btrfs_set_dir_name_len(dir_item, name_len); | 35 | btrfs_set_dir_name_len(dir_item, name_len); |
36 | name_ptr = (char *)(dir_item + 1); | 36 | name_ptr = (char *)(dir_item + 1); |
37 | memcpy(name_ptr, name, name_len); | 37 | btrfs_memcpy(root, path.nodes[0]->b_data, name_ptr, name, name_len); |
38 | if (name_ptr + name_len > path.nodes[0]->b_data + 4096) | 38 | btrfs_mark_buffer_dirty(path.nodes[0]); |
39 | WARN_ON(1); | ||
40 | mark_buffer_dirty(path.nodes[0]); | ||
41 | out: | 39 | out: |
42 | btrfs_release_path(root, &path); | 40 | btrfs_release_path(root, &path); |
43 | return ret; | 41 | return ret; |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 6c010463b9db..bb133104e2e9 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -8,6 +8,17 @@ | |||
8 | #include "disk-io.h" | 8 | #include "disk-io.h" |
9 | #include "transaction.h" | 9 | #include "transaction.h" |
10 | 10 | ||
11 | #define PATTERN 0xDEADBEEFUL | ||
12 | static inline void check_pattern(struct buffer_head *buf) | ||
13 | { | ||
14 | if (buf->b_private != (void *)PATTERN) | ||
15 | WARN_ON(1); | ||
16 | } | ||
17 | |||
18 | static inline void set_pattern(struct buffer_head *buf) | ||
19 | { | ||
20 | buf->b_private = (void *)PATTERN; | ||
21 | } | ||
11 | 22 | ||
12 | static int check_tree_block(struct btrfs_root *root, struct buffer_head *buf) | 23 | static int check_tree_block(struct btrfs_root *root, struct buffer_head *buf) |
13 | { | 24 | { |
@@ -51,8 +62,10 @@ struct buffer_head *btrfs_find_tree_block(struct btrfs_root *root, u64 blocknr) | |||
51 | } while (bh != head); | 62 | } while (bh != head); |
52 | out_unlock: | 63 | out_unlock: |
53 | unlock_page(page); | 64 | unlock_page(page); |
54 | if (ret) | 65 | if (ret) { |
55 | touch_buffer(ret); | 66 | touch_buffer(ret); |
67 | check_pattern(ret); | ||
68 | } | ||
56 | page_cache_release(page); | 69 | page_cache_release(page); |
57 | return ret; | 70 | return ret; |
58 | } | 71 | } |
@@ -82,6 +95,7 @@ struct buffer_head *btrfs_find_create_tree_block(struct btrfs_root *root, | |||
82 | bh->b_bdev = root->fs_info->sb->s_bdev; | 95 | bh->b_bdev = root->fs_info->sb->s_bdev; |
83 | bh->b_blocknr = first_block; | 96 | bh->b_blocknr = first_block; |
84 | set_buffer_mapped(bh); | 97 | set_buffer_mapped(bh); |
98 | set_pattern(bh); | ||
85 | } | 99 | } |
86 | if (bh->b_blocknr == blocknr) { | 100 | if (bh->b_blocknr == blocknr) { |
87 | ret = bh; | 101 | ret = bh; |
@@ -225,6 +239,7 @@ struct buffer_head *read_tree_block(struct btrfs_root *root, u64 blocknr) | |||
225 | if (!buffer_uptodate(bh)) | 239 | if (!buffer_uptodate(bh)) |
226 | goto fail; | 240 | goto fail; |
227 | csum_tree_block(root, bh, 1); | 241 | csum_tree_block(root, bh, 1); |
242 | set_pattern(bh); | ||
228 | } else { | 243 | } else { |
229 | unlock_buffer(bh); | 244 | unlock_buffer(bh); |
230 | } | 245 | } |
@@ -240,6 +255,7 @@ fail: | |||
240 | int dirty_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 255 | int dirty_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
241 | struct buffer_head *buf) | 256 | struct buffer_head *buf) |
242 | { | 257 | { |
258 | WARN_ON(atomic_read(&buf->b_count) == 0); | ||
243 | mark_buffer_dirty(buf); | 259 | mark_buffer_dirty(buf); |
244 | return 0; | 260 | return 0; |
245 | } | 261 | } |
@@ -247,6 +263,7 @@ int dirty_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
247 | int clean_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 263 | int clean_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
248 | struct buffer_head *buf) | 264 | struct buffer_head *buf) |
249 | { | 265 | { |
266 | WARN_ON(atomic_read(&buf->b_count) == 0); | ||
250 | clear_buffer_dirty(buf); | 267 | clear_buffer_dirty(buf); |
251 | return 0; | 268 | return 0; |
252 | } | 269 | } |
@@ -431,6 +448,7 @@ int close_ctree(struct btrfs_root *root) | |||
431 | 448 | ||
432 | void btrfs_block_release(struct btrfs_root *root, struct buffer_head *buf) | 449 | void btrfs_block_release(struct btrfs_root *root, struct buffer_head *buf) |
433 | { | 450 | { |
451 | check_pattern(buf); | ||
434 | brelse(buf); | 452 | brelse(buf); |
435 | } | 453 | } |
436 | 454 | ||
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index b2ae8e768b6c..c4194dab7a33 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -39,7 +39,7 @@ static int inc_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root | |||
39 | item = btrfs_item_ptr(l, path.slots[0], struct btrfs_extent_item); | 39 | item = btrfs_item_ptr(l, path.slots[0], struct btrfs_extent_item); |
40 | refs = btrfs_extent_refs(item); | 40 | refs = btrfs_extent_refs(item); |
41 | btrfs_set_extent_refs(item, refs + 1); | 41 | btrfs_set_extent_refs(item, refs + 1); |
42 | mark_buffer_dirty(path.nodes[0]); | 42 | btrfs_mark_buffer_dirty(path.nodes[0]); |
43 | 43 | ||
44 | btrfs_release_path(root->fs_info->extent_root, &path); | 44 | btrfs_release_path(root->fs_info->extent_root, &path); |
45 | finish_current_insert(trans, root->fs_info->extent_root); | 45 | finish_current_insert(trans, root->fs_info->extent_root); |
@@ -177,10 +177,10 @@ static int pin_down_block(struct btrfs_root *root, u64 blocknr, int pending) | |||
177 | header = btrfs_buffer_header(bh); | 177 | header = btrfs_buffer_header(bh); |
178 | if (btrfs_header_generation(header) == | 178 | if (btrfs_header_generation(header) == |
179 | root->fs_info->running_transaction->transid) { | 179 | root->fs_info->running_transaction->transid) { |
180 | brelse(bh); | 180 | btrfs_block_release(root, bh); |
181 | return 0; | 181 | return 0; |
182 | } | 182 | } |
183 | brelse(bh); | 183 | btrfs_block_release(root, bh); |
184 | } | 184 | } |
185 | err = set_radix_bit(&root->fs_info->pinned_radix, blocknr); | 185 | err = set_radix_bit(&root->fs_info->pinned_radix, blocknr); |
186 | } else { | 186 | } else { |
@@ -224,7 +224,7 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | |||
224 | BUG_ON(ei->refs == 0); | 224 | BUG_ON(ei->refs == 0); |
225 | refs = btrfs_extent_refs(ei) - 1; | 225 | refs = btrfs_extent_refs(ei) - 1; |
226 | btrfs_set_extent_refs(ei, refs); | 226 | btrfs_set_extent_refs(ei, refs); |
227 | mark_buffer_dirty(path.nodes[0]); | 227 | btrfs_mark_buffer_dirty(path.nodes[0]); |
228 | if (refs == 0) { | 228 | if (refs == 0) { |
229 | u64 super_blocks_used; | 229 | u64 super_blocks_used; |
230 | 230 | ||
diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c index 2d2c23ca7cbf..c3992b7b0c60 100644 --- a/fs/btrfs/file-item.c +++ b/fs/btrfs/file-item.c | |||
@@ -34,7 +34,7 @@ int btrfs_alloc_file_extent(struct btrfs_trans_handle *trans, | |||
34 | btrfs_set_file_extent_offset(item, 0); | 34 | btrfs_set_file_extent_offset(item, 0); |
35 | btrfs_set_file_extent_num_blocks(item, ins.offset); | 35 | btrfs_set_file_extent_num_blocks(item, ins.offset); |
36 | btrfs_set_file_extent_generation(item, trans->transid); | 36 | btrfs_set_file_extent_generation(item, trans->transid); |
37 | mark_buffer_dirty(path.nodes[0]); | 37 | btrfs_mark_buffer_dirty(path.nodes[0]); |
38 | *result = ins.objectid; | 38 | *result = ins.objectid; |
39 | btrfs_release_path(root, &path); | 39 | btrfs_release_path(root, &path); |
40 | return 0; | 40 | return 0; |
@@ -81,7 +81,7 @@ int btrfs_csum_file_block(struct btrfs_trans_handle *trans, | |||
81 | struct btrfs_csum_item); | 81 | struct btrfs_csum_item); |
82 | ret = 0; | 82 | ret = 0; |
83 | ret = btrfs_csum_data(root, data, len, item->csum); | 83 | ret = btrfs_csum_data(root, data, len, item->csum); |
84 | mark_buffer_dirty(path.nodes[0]); | 84 | btrfs_mark_buffer_dirty(path.nodes[0]); |
85 | fail: | 85 | fail: |
86 | btrfs_release_path(root, &path); | 86 | btrfs_release_path(root, &path); |
87 | return ret; | 87 | return ret; |
diff --git a/fs/btrfs/inode-map.c b/fs/btrfs/inode-map.c index 1b2c5e043508..fa4adb81b149 100644 --- a/fs/btrfs/inode-map.c +++ b/fs/btrfs/inode-map.c | |||
@@ -109,7 +109,7 @@ int btrfs_insert_inode_map(struct btrfs_trans_handle *trans, | |||
109 | inode_item = btrfs_item_ptr(btrfs_buffer_leaf(path.nodes[0]), | 109 | inode_item = btrfs_item_ptr(btrfs_buffer_leaf(path.nodes[0]), |
110 | path.slots[0], struct btrfs_inode_map_item); | 110 | path.slots[0], struct btrfs_inode_map_item); |
111 | btrfs_cpu_key_to_disk(&inode_item->key, location); | 111 | btrfs_cpu_key_to_disk(&inode_item->key, location); |
112 | mark_buffer_dirty(path.nodes[0]); | 112 | btrfs_mark_buffer_dirty(path.nodes[0]); |
113 | out: | 113 | out: |
114 | btrfs_release_path(inode_root, &path); | 114 | btrfs_release_path(inode_root, &path); |
115 | return ret; | 115 | return ret; |
diff --git a/fs/btrfs/root-tree.c b/fs/btrfs/root-tree.c index a821b5d1e233..f37dab87de16 100644 --- a/fs/btrfs/root-tree.c +++ b/fs/btrfs/root-tree.c | |||
@@ -45,6 +45,7 @@ int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root | |||
45 | struct btrfs_leaf *l; | 45 | struct btrfs_leaf *l; |
46 | int ret; | 46 | int ret; |
47 | int slot; | 47 | int slot; |
48 | struct btrfs_root_item *update_item; | ||
48 | 49 | ||
49 | btrfs_init_path(&path); | 50 | btrfs_init_path(&path); |
50 | ret = btrfs_search_slot(trans, root, key, &path, 0, 1); | 51 | ret = btrfs_search_slot(trans, root, key, &path, 0, 1); |
@@ -53,9 +54,9 @@ int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root | |||
53 | BUG_ON(ret != 0); | 54 | BUG_ON(ret != 0); |
54 | l = btrfs_buffer_leaf(path.nodes[0]); | 55 | l = btrfs_buffer_leaf(path.nodes[0]); |
55 | slot = path.slots[0]; | 56 | slot = path.slots[0]; |
56 | memcpy(btrfs_item_ptr(l, slot, struct btrfs_root_item), item, | 57 | update_item = btrfs_item_ptr(l, slot, struct btrfs_root_item); |
57 | sizeof(*item)); | 58 | btrfs_memcpy(root, l, update_item, item, sizeof(*item)); |
58 | mark_buffer_dirty(path.nodes[0]); | 59 | btrfs_mark_buffer_dirty(path.nodes[0]); |
59 | out: | 60 | out: |
60 | btrfs_release_path(root, &path); | 61 | btrfs_release_path(root, &path); |
61 | return ret; | 62 | return ret; |
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index ab5419eea93a..894a70bf26d2 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -557,7 +557,7 @@ static int btrfs_update_inode(struct btrfs_trans_handle *trans, | |||
557 | struct btrfs_inode_item); | 557 | struct btrfs_inode_item); |
558 | 558 | ||
559 | fill_inode_item(inode_item, inode); | 559 | fill_inode_item(inode_item, inode); |
560 | mark_buffer_dirty(path.nodes[0]); | 560 | btrfs_mark_buffer_dirty(path.nodes[0]); |
561 | failed: | 561 | failed: |
562 | btrfs_release_path(root, &path); | 562 | btrfs_release_path(root, &path); |
563 | return 0; | 563 | return 0; |
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index a146463c5049..84c4e278ce2e 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -66,6 +66,7 @@ int btrfs_end_transaction(struct btrfs_trans_handle *trans, | |||
66 | cur_trans->num_writers--; | 66 | cur_trans->num_writers--; |
67 | put_transaction(cur_trans); | 67 | put_transaction(cur_trans); |
68 | mutex_unlock(&root->fs_info->trans_mutex); | 68 | mutex_unlock(&root->fs_info->trans_mutex); |
69 | memset(trans, 0, sizeof(*trans)); | ||
69 | kfree(trans); | 70 | kfree(trans); |
70 | return 0; | 71 | return 0; |
71 | } | 72 | } |