diff options
Diffstat (limited to 'fs/btrfs/ctree.c')
| -rw-r--r-- | fs/btrfs/ctree.c | 289 | 
1 files changed, 144 insertions, 145 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index ed504607d8ec..64346721173f 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c  | |||
| @@ -274,8 +274,7 @@ int btrfs_copy_root(struct btrfs_trans_handle *trans, | |||
| 274 | else | 274 | else | 
| 275 | btrfs_set_header_owner(cow, new_root_objectid); | 275 | btrfs_set_header_owner(cow, new_root_objectid); | 
| 276 | 276 | ||
| 277 | write_extent_buffer(cow, root->fs_info->fsid, | 277 | write_extent_buffer(cow, root->fs_info->fsid, btrfs_header_fsid(cow), | 
| 278 | (unsigned long)btrfs_header_fsid(cow), | ||
| 279 | BTRFS_FSID_SIZE); | 278 | BTRFS_FSID_SIZE); | 
| 280 | 279 | ||
| 281 | WARN_ON(btrfs_header_generation(buf) > trans->transid); | 280 | WARN_ON(btrfs_header_generation(buf) > trans->transid); | 
| @@ -484,8 +483,27 @@ __tree_mod_log_insert(struct btrfs_fs_info *fs_info, struct tree_mod_elem *tm) | |||
| 484 | struct rb_node **new; | 483 | struct rb_node **new; | 
| 485 | struct rb_node *parent = NULL; | 484 | struct rb_node *parent = NULL; | 
| 486 | struct tree_mod_elem *cur; | 485 | struct tree_mod_elem *cur; | 
| 486 | int ret = 0; | ||
| 487 | |||
| 488 | BUG_ON(!tm); | ||
| 489 | |||
| 490 | tree_mod_log_write_lock(fs_info); | ||
| 491 | if (list_empty(&fs_info->tree_mod_seq_list)) { | ||
| 492 | tree_mod_log_write_unlock(fs_info); | ||
| 493 | /* | ||
| 494 | * Ok we no longer care about logging modifications, free up tm | ||
| 495 | * and return 0. Any callers shouldn't be using tm after | ||
| 496 | * calling tree_mod_log_insert, but if they do we can just | ||
| 497 | * change this to return a special error code to let the callers | ||
| 498 | * do their own thing. | ||
| 499 | */ | ||
| 500 | kfree(tm); | ||
| 501 | return 0; | ||
| 502 | } | ||
| 487 | 503 | ||
| 488 | BUG_ON(!tm || !tm->seq); | 504 | spin_lock(&fs_info->tree_mod_seq_lock); | 
| 505 | tm->seq = btrfs_inc_tree_mod_seq_minor(fs_info); | ||
| 506 | spin_unlock(&fs_info->tree_mod_seq_lock); | ||
| 489 | 507 | ||
| 490 | tm_root = &fs_info->tree_mod_log; | 508 | tm_root = &fs_info->tree_mod_log; | 
| 491 | new = &tm_root->rb_node; | 509 | new = &tm_root->rb_node; | 
| @@ -501,14 +519,17 @@ __tree_mod_log_insert(struct btrfs_fs_info *fs_info, struct tree_mod_elem *tm) | |||
| 501 | else if (cur->seq > tm->seq) | 519 | else if (cur->seq > tm->seq) | 
| 502 | new = &((*new)->rb_right); | 520 | new = &((*new)->rb_right); | 
| 503 | else { | 521 | else { | 
| 522 | ret = -EEXIST; | ||
| 504 | kfree(tm); | 523 | kfree(tm); | 
| 505 | return -EEXIST; | 524 | goto out; | 
| 506 | } | 525 | } | 
| 507 | } | 526 | } | 
| 508 | 527 | ||
| 509 | rb_link_node(&tm->node, parent, new); | 528 | rb_link_node(&tm->node, parent, new); | 
| 510 | rb_insert_color(&tm->node, tm_root); | 529 | rb_insert_color(&tm->node, tm_root); | 
| 511 | return 0; | 530 | out: | 
| 531 | tree_mod_log_write_unlock(fs_info); | ||
| 532 | return ret; | ||
| 512 | } | 533 | } | 
| 513 | 534 | ||
| 514 | /* | 535 | /* | 
| @@ -524,57 +545,19 @@ static inline int tree_mod_dont_log(struct btrfs_fs_info *fs_info, | |||
| 524 | return 1; | 545 | return 1; | 
| 525 | if (eb && btrfs_header_level(eb) == 0) | 546 | if (eb && btrfs_header_level(eb) == 0) | 
| 526 | return 1; | 547 | return 1; | 
| 527 | |||
| 528 | tree_mod_log_write_lock(fs_info); | ||
| 529 | if (list_empty(&fs_info->tree_mod_seq_list)) { | ||
| 530 | /* | ||
| 531 | * someone emptied the list while we were waiting for the lock. | ||
| 532 | * we must not add to the list when no blocker exists. | ||
| 533 | */ | ||
| 534 | tree_mod_log_write_unlock(fs_info); | ||
| 535 | return 1; | ||
| 536 | } | ||
| 537 | |||
| 538 | return 0; | 548 | return 0; | 
| 539 | } | 549 | } | 
| 540 | 550 | ||
| 541 | /* | ||
| 542 | * This allocates memory and gets a tree modification sequence number. | ||
| 543 | * | ||
| 544 | * Returns <0 on error. | ||
| 545 | * Returns >0 (the added sequence number) on success. | ||
| 546 | */ | ||
| 547 | static inline int tree_mod_alloc(struct btrfs_fs_info *fs_info, gfp_t flags, | ||
| 548 | struct tree_mod_elem **tm_ret) | ||
| 549 | { | ||
| 550 | struct tree_mod_elem *tm; | ||
| 551 | |||
| 552 | /* | ||
| 553 | * once we switch from spin locks to something different, we should | ||
| 554 | * honor the flags parameter here. | ||
| 555 | */ | ||
| 556 | tm = *tm_ret = kzalloc(sizeof(*tm), GFP_ATOMIC); | ||
| 557 | if (!tm) | ||
| 558 | return -ENOMEM; | ||
| 559 | |||
| 560 | spin_lock(&fs_info->tree_mod_seq_lock); | ||
| 561 | tm->seq = btrfs_inc_tree_mod_seq_minor(fs_info); | ||
| 562 | spin_unlock(&fs_info->tree_mod_seq_lock); | ||
| 563 | |||
| 564 | return tm->seq; | ||
| 565 | } | ||
| 566 | |||
| 567 | static inline int | 551 | static inline int | 
| 568 | __tree_mod_log_insert_key(struct btrfs_fs_info *fs_info, | 552 | __tree_mod_log_insert_key(struct btrfs_fs_info *fs_info, | 
| 569 | struct extent_buffer *eb, int slot, | 553 | struct extent_buffer *eb, int slot, | 
| 570 | enum mod_log_op op, gfp_t flags) | 554 | enum mod_log_op op, gfp_t flags) | 
| 571 | { | 555 | { | 
| 572 | int ret; | ||
| 573 | struct tree_mod_elem *tm; | 556 | struct tree_mod_elem *tm; | 
| 574 | 557 | ||
| 575 | ret = tree_mod_alloc(fs_info, flags, &tm); | 558 | tm = kzalloc(sizeof(*tm), flags); | 
| 576 | if (ret < 0) | 559 | if (!tm) | 
| 577 | return ret; | 560 | return -ENOMEM; | 
| 578 | 561 | ||
| 579 | tm->index = eb->start >> PAGE_CACHE_SHIFT; | 562 | tm->index = eb->start >> PAGE_CACHE_SHIFT; | 
| 580 | if (op != MOD_LOG_KEY_ADD) { | 563 | if (op != MOD_LOG_KEY_ADD) { | 
| @@ -589,34 +572,14 @@ __tree_mod_log_insert_key(struct btrfs_fs_info *fs_info, | |||
| 589 | } | 572 | } | 
| 590 | 573 | ||
| 591 | static noinline int | 574 | static noinline int | 
| 592 | tree_mod_log_insert_key_mask(struct btrfs_fs_info *fs_info, | 575 | tree_mod_log_insert_key(struct btrfs_fs_info *fs_info, | 
| 593 | struct extent_buffer *eb, int slot, | 576 | struct extent_buffer *eb, int slot, | 
| 594 | enum mod_log_op op, gfp_t flags) | 577 | enum mod_log_op op, gfp_t flags) | 
| 595 | { | 578 | { | 
| 596 | int ret; | ||
| 597 | |||
| 598 | if (tree_mod_dont_log(fs_info, eb)) | 579 | if (tree_mod_dont_log(fs_info, eb)) | 
| 599 | return 0; | 580 | return 0; | 
| 600 | 581 | ||
| 601 | ret = __tree_mod_log_insert_key(fs_info, eb, slot, op, flags); | 582 | return __tree_mod_log_insert_key(fs_info, eb, slot, op, flags); | 
| 602 | |||
| 603 | tree_mod_log_write_unlock(fs_info); | ||
| 604 | return ret; | ||
| 605 | } | ||
| 606 | |||
| 607 | static noinline int | ||
| 608 | tree_mod_log_insert_key(struct btrfs_fs_info *fs_info, struct extent_buffer *eb, | ||
| 609 | int slot, enum mod_log_op op) | ||
| 610 | { | ||
| 611 | return tree_mod_log_insert_key_mask(fs_info, eb, slot, op, GFP_NOFS); | ||
| 612 | } | ||
| 613 | |||
| 614 | static noinline int | ||
| 615 | tree_mod_log_insert_key_locked(struct btrfs_fs_info *fs_info, | ||
| 616 | struct extent_buffer *eb, int slot, | ||
| 617 | enum mod_log_op op) | ||
| 618 | { | ||
| 619 | return __tree_mod_log_insert_key(fs_info, eb, slot, op, GFP_NOFS); | ||
| 620 | } | 583 | } | 
| 621 | 584 | ||
| 622 | static noinline int | 585 | static noinline int | 
| @@ -637,14 +600,14 @@ tree_mod_log_insert_move(struct btrfs_fs_info *fs_info, | |||
| 637 | * buffer, i.e. dst_slot < src_slot. | 600 | * buffer, i.e. dst_slot < src_slot. | 
| 638 | */ | 601 | */ | 
| 639 | for (i = 0; i + dst_slot < src_slot && i < nr_items; i++) { | 602 | for (i = 0; i + dst_slot < src_slot && i < nr_items; i++) { | 
| 640 | ret = tree_mod_log_insert_key_locked(fs_info, eb, i + dst_slot, | 603 | ret = __tree_mod_log_insert_key(fs_info, eb, i + dst_slot, | 
| 641 | MOD_LOG_KEY_REMOVE_WHILE_MOVING); | 604 | MOD_LOG_KEY_REMOVE_WHILE_MOVING, GFP_NOFS); | 
| 642 | BUG_ON(ret < 0); | 605 | BUG_ON(ret < 0); | 
| 643 | } | 606 | } | 
| 644 | 607 | ||
| 645 | ret = tree_mod_alloc(fs_info, flags, &tm); | 608 | tm = kzalloc(sizeof(*tm), flags); | 
| 646 | if (ret < 0) | 609 | if (!tm) | 
| 647 | goto out; | 610 | return -ENOMEM; | 
| 648 | 611 | ||
| 649 | tm->index = eb->start >> PAGE_CACHE_SHIFT; | 612 | tm->index = eb->start >> PAGE_CACHE_SHIFT; | 
| 650 | tm->slot = src_slot; | 613 | tm->slot = src_slot; | 
| @@ -652,10 +615,7 @@ tree_mod_log_insert_move(struct btrfs_fs_info *fs_info, | |||
| 652 | tm->move.nr_items = nr_items; | 615 | tm->move.nr_items = nr_items; | 
| 653 | tm->op = MOD_LOG_MOVE_KEYS; | 616 | tm->op = MOD_LOG_MOVE_KEYS; | 
| 654 | 617 | ||
| 655 | ret = __tree_mod_log_insert(fs_info, tm); | 618 | return __tree_mod_log_insert(fs_info, tm); | 
| 656 | out: | ||
| 657 | tree_mod_log_write_unlock(fs_info); | ||
| 658 | return ret; | ||
| 659 | } | 619 | } | 
| 660 | 620 | ||
| 661 | static inline void | 621 | static inline void | 
| @@ -670,8 +630,8 @@ __tree_mod_log_free_eb(struct btrfs_fs_info *fs_info, struct extent_buffer *eb) | |||
| 670 | 630 | ||
| 671 | nritems = btrfs_header_nritems(eb); | 631 | nritems = btrfs_header_nritems(eb); | 
| 672 | for (i = nritems - 1; i >= 0; i--) { | 632 | for (i = nritems - 1; i >= 0; i--) { | 
| 673 | ret = tree_mod_log_insert_key_locked(fs_info, eb, i, | 633 | ret = __tree_mod_log_insert_key(fs_info, eb, i, | 
| 674 | MOD_LOG_KEY_REMOVE_WHILE_FREEING); | 634 | MOD_LOG_KEY_REMOVE_WHILE_FREEING, GFP_NOFS); | 
| 675 | BUG_ON(ret < 0); | 635 | BUG_ON(ret < 0); | 
| 676 | } | 636 | } | 
| 677 | } | 637 | } | 
| @@ -683,7 +643,6 @@ tree_mod_log_insert_root(struct btrfs_fs_info *fs_info, | |||
| 683 | int log_removal) | 643 | int log_removal) | 
| 684 | { | 644 | { | 
| 685 | struct tree_mod_elem *tm; | 645 | struct tree_mod_elem *tm; | 
| 686 | int ret; | ||
| 687 | 646 | ||
| 688 | if (tree_mod_dont_log(fs_info, NULL)) | 647 | if (tree_mod_dont_log(fs_info, NULL)) | 
| 689 | return 0; | 648 | return 0; | 
| @@ -691,9 +650,9 @@ tree_mod_log_insert_root(struct btrfs_fs_info *fs_info, | |||
| 691 | if (log_removal) | 650 | if (log_removal) | 
| 692 | __tree_mod_log_free_eb(fs_info, old_root); | 651 | __tree_mod_log_free_eb(fs_info, old_root); | 
| 693 | 652 | ||
| 694 | ret = tree_mod_alloc(fs_info, flags, &tm); | 653 | tm = kzalloc(sizeof(*tm), flags); | 
| 695 | if (ret < 0) | 654 | if (!tm) | 
| 696 | goto out; | 655 | return -ENOMEM; | 
| 697 | 656 | ||
| 698 | tm->index = new_root->start >> PAGE_CACHE_SHIFT; | 657 | tm->index = new_root->start >> PAGE_CACHE_SHIFT; | 
| 699 | tm->old_root.logical = old_root->start; | 658 | tm->old_root.logical = old_root->start; | 
| @@ -701,10 +660,7 @@ tree_mod_log_insert_root(struct btrfs_fs_info *fs_info, | |||
| 701 | tm->generation = btrfs_header_generation(old_root); | 660 | tm->generation = btrfs_header_generation(old_root); | 
| 702 | tm->op = MOD_LOG_ROOT_REPLACE; | 661 | tm->op = MOD_LOG_ROOT_REPLACE; | 
| 703 | 662 | ||
| 704 | ret = __tree_mod_log_insert(fs_info, tm); | 663 | return __tree_mod_log_insert(fs_info, tm); | 
| 705 | out: | ||
| 706 | tree_mod_log_write_unlock(fs_info); | ||
| 707 | return ret; | ||
| 708 | } | 664 | } | 
| 709 | 665 | ||
| 710 | static struct tree_mod_elem * | 666 | static struct tree_mod_elem * | 
| @@ -784,23 +740,20 @@ tree_mod_log_eb_copy(struct btrfs_fs_info *fs_info, struct extent_buffer *dst, | |||
| 784 | if (tree_mod_dont_log(fs_info, NULL)) | 740 | if (tree_mod_dont_log(fs_info, NULL)) | 
| 785 | return; | 741 | return; | 
| 786 | 742 | ||
| 787 | if (btrfs_header_level(dst) == 0 && btrfs_header_level(src) == 0) { | 743 | if (btrfs_header_level(dst) == 0 && btrfs_header_level(src) == 0) | 
| 788 | tree_mod_log_write_unlock(fs_info); | ||
| 789 | return; | 744 | return; | 
| 790 | } | ||
| 791 | 745 | ||
| 792 | for (i = 0; i < nr_items; i++) { | 746 | for (i = 0; i < nr_items; i++) { | 
| 793 | ret = tree_mod_log_insert_key_locked(fs_info, src, | 747 | ret = __tree_mod_log_insert_key(fs_info, src, | 
| 794 | i + src_offset, | 748 | i + src_offset, | 
| 795 | MOD_LOG_KEY_REMOVE); | 749 | MOD_LOG_KEY_REMOVE, GFP_NOFS); | 
| 796 | BUG_ON(ret < 0); | 750 | BUG_ON(ret < 0); | 
| 797 | ret = tree_mod_log_insert_key_locked(fs_info, dst, | 751 | ret = __tree_mod_log_insert_key(fs_info, dst, | 
| 798 | i + dst_offset, | 752 | i + dst_offset, | 
| 799 | MOD_LOG_KEY_ADD); | 753 | MOD_LOG_KEY_ADD, | 
| 754 | GFP_NOFS); | ||
| 800 | BUG_ON(ret < 0); | 755 | BUG_ON(ret < 0); | 
| 801 | } | 756 | } | 
| 802 | |||
| 803 | tree_mod_log_write_unlock(fs_info); | ||
| 804 | } | 757 | } | 
| 805 | 758 | ||
| 806 | static inline void | 759 | static inline void | 
| @@ -819,9 +772,9 @@ tree_mod_log_set_node_key(struct btrfs_fs_info *fs_info, | |||
| 819 | { | 772 | { | 
| 820 | int ret; | 773 | int ret; | 
| 821 | 774 | ||
| 822 | ret = tree_mod_log_insert_key_mask(fs_info, eb, slot, | 775 | ret = __tree_mod_log_insert_key(fs_info, eb, slot, | 
| 823 | MOD_LOG_KEY_REPLACE, | 776 | MOD_LOG_KEY_REPLACE, | 
| 824 | atomic ? GFP_ATOMIC : GFP_NOFS); | 777 | atomic ? GFP_ATOMIC : GFP_NOFS); | 
| 825 | BUG_ON(ret < 0); | 778 | BUG_ON(ret < 0); | 
| 826 | } | 779 | } | 
| 827 | 780 | ||
| @@ -830,10 +783,7 @@ tree_mod_log_free_eb(struct btrfs_fs_info *fs_info, struct extent_buffer *eb) | |||
| 830 | { | 783 | { | 
| 831 | if (tree_mod_dont_log(fs_info, eb)) | 784 | if (tree_mod_dont_log(fs_info, eb)) | 
| 832 | return; | 785 | return; | 
| 833 | |||
| 834 | __tree_mod_log_free_eb(fs_info, eb); | 786 | __tree_mod_log_free_eb(fs_info, eb); | 
| 835 | |||
| 836 | tree_mod_log_write_unlock(fs_info); | ||
| 837 | } | 787 | } | 
| 838 | 788 | ||
| 839 | static noinline void | 789 | static noinline void | 
| @@ -1046,8 +996,7 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans, | |||
| 1046 | else | 996 | else | 
| 1047 | btrfs_set_header_owner(cow, root->root_key.objectid); | 997 | btrfs_set_header_owner(cow, root->root_key.objectid); | 
| 1048 | 998 | ||
| 1049 | write_extent_buffer(cow, root->fs_info->fsid, | 999 | write_extent_buffer(cow, root->fs_info->fsid, btrfs_header_fsid(cow), | 
| 1050 | (unsigned long)btrfs_header_fsid(cow), | ||
| 1051 | BTRFS_FSID_SIZE); | 1000 | BTRFS_FSID_SIZE); | 
| 1052 | 1001 | ||
| 1053 | ret = update_ref_for_cow(trans, root, buf, cow, &last_ref); | 1002 | ret = update_ref_for_cow(trans, root, buf, cow, &last_ref); | 
| @@ -1083,7 +1032,7 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans, | |||
| 1083 | 1032 | ||
| 1084 | WARN_ON(trans->transid != btrfs_header_generation(parent)); | 1033 | WARN_ON(trans->transid != btrfs_header_generation(parent)); | 
| 1085 | tree_mod_log_insert_key(root->fs_info, parent, parent_slot, | 1034 | tree_mod_log_insert_key(root->fs_info, parent, parent_slot, | 
| 1086 | MOD_LOG_KEY_REPLACE); | 1035 | MOD_LOG_KEY_REPLACE, GFP_NOFS); | 
| 1087 | btrfs_set_node_blockptr(parent, parent_slot, | 1036 | btrfs_set_node_blockptr(parent, parent_slot, | 
| 1088 | cow->start); | 1037 | cow->start); | 
| 1089 | btrfs_set_node_ptr_generation(parent, parent_slot, | 1038 | btrfs_set_node_ptr_generation(parent, parent_slot, | 
| @@ -1116,7 +1065,7 @@ __tree_mod_log_oldest_root(struct btrfs_fs_info *fs_info, | |||
| 1116 | int looped = 0; | 1065 | int looped = 0; | 
| 1117 | 1066 | ||
| 1118 | if (!time_seq) | 1067 | if (!time_seq) | 
| 1119 | return 0; | 1068 | return NULL; | 
| 1120 | 1069 | ||
| 1121 | /* | 1070 | /* | 
| 1122 | * the very last operation that's logged for a root is the replacement | 1071 | * the very last operation that's logged for a root is the replacement | 
| @@ -1127,7 +1076,7 @@ __tree_mod_log_oldest_root(struct btrfs_fs_info *fs_info, | |||
| 1127 | tm = tree_mod_log_search_oldest(fs_info, root_logical, | 1076 | tm = tree_mod_log_search_oldest(fs_info, root_logical, | 
| 1128 | time_seq); | 1077 | time_seq); | 
| 1129 | if (!looped && !tm) | 1078 | if (!looped && !tm) | 
| 1130 | return 0; | 1079 | return NULL; | 
| 1131 | /* | 1080 | /* | 
| 1132 | * if there are no tree operation for the oldest root, we simply | 1081 | * if there are no tree operation for the oldest root, we simply | 
| 1133 | * return it. this should only happen if that (old) root is at | 1082 | * return it. this should only happen if that (old) root is at | 
| @@ -1240,8 +1189,8 @@ __tree_mod_log_rewind(struct btrfs_fs_info *fs_info, struct extent_buffer *eb, | |||
| 1240 | * is freed (its refcount is decremented). | 1189 | * is freed (its refcount is decremented). | 
| 1241 | */ | 1190 | */ | 
| 1242 | static struct extent_buffer * | 1191 | static struct extent_buffer * | 
| 1243 | tree_mod_log_rewind(struct btrfs_fs_info *fs_info, struct extent_buffer *eb, | 1192 | tree_mod_log_rewind(struct btrfs_fs_info *fs_info, struct btrfs_path *path, | 
| 1244 | u64 time_seq) | 1193 | struct extent_buffer *eb, u64 time_seq) | 
| 1245 | { | 1194 | { | 
| 1246 | struct extent_buffer *eb_rewin; | 1195 | struct extent_buffer *eb_rewin; | 
| 1247 | struct tree_mod_elem *tm; | 1196 | struct tree_mod_elem *tm; | 
| @@ -1256,11 +1205,18 @@ tree_mod_log_rewind(struct btrfs_fs_info *fs_info, struct extent_buffer *eb, | |||
| 1256 | if (!tm) | 1205 | if (!tm) | 
| 1257 | return eb; | 1206 | return eb; | 
| 1258 | 1207 | ||
| 1208 | btrfs_set_path_blocking(path); | ||
| 1209 | btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK); | ||
| 1210 | |||
| 1259 | if (tm->op == MOD_LOG_KEY_REMOVE_WHILE_FREEING) { | 1211 | if (tm->op == MOD_LOG_KEY_REMOVE_WHILE_FREEING) { | 
| 1260 | BUG_ON(tm->slot != 0); | 1212 | BUG_ON(tm->slot != 0); | 
| 1261 | eb_rewin = alloc_dummy_extent_buffer(eb->start, | 1213 | eb_rewin = alloc_dummy_extent_buffer(eb->start, | 
| 1262 | fs_info->tree_root->nodesize); | 1214 | fs_info->tree_root->nodesize); | 
| 1263 | BUG_ON(!eb_rewin); | 1215 | if (!eb_rewin) { | 
| 1216 | btrfs_tree_read_unlock_blocking(eb); | ||
| 1217 | free_extent_buffer(eb); | ||
| 1218 | return NULL; | ||
| 1219 | } | ||
| 1264 | btrfs_set_header_bytenr(eb_rewin, eb->start); | 1220 | btrfs_set_header_bytenr(eb_rewin, eb->start); | 
| 1265 | btrfs_set_header_backref_rev(eb_rewin, | 1221 | btrfs_set_header_backref_rev(eb_rewin, | 
| 1266 | btrfs_header_backref_rev(eb)); | 1222 | btrfs_header_backref_rev(eb)); | 
| @@ -1268,10 +1224,15 @@ tree_mod_log_rewind(struct btrfs_fs_info *fs_info, struct extent_buffer *eb, | |||
| 1268 | btrfs_set_header_level(eb_rewin, btrfs_header_level(eb)); | 1224 | btrfs_set_header_level(eb_rewin, btrfs_header_level(eb)); | 
| 1269 | } else { | 1225 | } else { | 
| 1270 | eb_rewin = btrfs_clone_extent_buffer(eb); | 1226 | eb_rewin = btrfs_clone_extent_buffer(eb); | 
| 1271 | BUG_ON(!eb_rewin); | 1227 | if (!eb_rewin) { | 
| 1228 | btrfs_tree_read_unlock_blocking(eb); | ||
| 1229 | free_extent_buffer(eb); | ||
| 1230 | return NULL; | ||
| 1231 | } | ||
| 1272 | } | 1232 | } | 
| 1273 | 1233 | ||
| 1274 | btrfs_tree_read_unlock(eb); | 1234 | btrfs_clear_path_blocking(path, NULL, BTRFS_READ_LOCK); | 
| 1235 | btrfs_tree_read_unlock_blocking(eb); | ||
| 1275 | free_extent_buffer(eb); | 1236 | free_extent_buffer(eb); | 
| 1276 | 1237 | ||
| 1277 | extent_buffer_get(eb_rewin); | 1238 | extent_buffer_get(eb_rewin); | 
| @@ -1335,8 +1296,9 @@ get_old_root(struct btrfs_root *root, u64 time_seq) | |||
| 1335 | free_extent_buffer(eb_root); | 1296 | free_extent_buffer(eb_root); | 
| 1336 | eb = alloc_dummy_extent_buffer(logical, root->nodesize); | 1297 | eb = alloc_dummy_extent_buffer(logical, root->nodesize); | 
| 1337 | } else { | 1298 | } else { | 
| 1299 | btrfs_set_lock_blocking_rw(eb_root, BTRFS_READ_LOCK); | ||
| 1338 | eb = btrfs_clone_extent_buffer(eb_root); | 1300 | eb = btrfs_clone_extent_buffer(eb_root); | 
| 1339 | btrfs_tree_read_unlock(eb_root); | 1301 | btrfs_tree_read_unlock_blocking(eb_root); | 
| 1340 | free_extent_buffer(eb_root); | 1302 | free_extent_buffer(eb_root); | 
| 1341 | } | 1303 | } | 
| 1342 | 1304 | ||
| @@ -1419,14 +1381,12 @@ noinline int btrfs_cow_block(struct btrfs_trans_handle *trans, | |||
| 1419 | 1381 | ||
| 1420 | if (trans->transaction != root->fs_info->running_transaction) | 1382 | if (trans->transaction != root->fs_info->running_transaction) | 
| 1421 | WARN(1, KERN_CRIT "trans %llu running %llu\n", | 1383 | WARN(1, KERN_CRIT "trans %llu running %llu\n", | 
| 1422 | (unsigned long long)trans->transid, | 1384 | trans->transid, | 
| 1423 | (unsigned long long) | ||
| 1424 | root->fs_info->running_transaction->transid); | 1385 | root->fs_info->running_transaction->transid); | 
| 1425 | 1386 | ||
| 1426 | if (trans->transid != root->fs_info->generation) | 1387 | if (trans->transid != root->fs_info->generation) | 
| 1427 | WARN(1, KERN_CRIT "trans %llu running %llu\n", | 1388 | WARN(1, KERN_CRIT "trans %llu running %llu\n", | 
| 1428 | (unsigned long long)trans->transid, | 1389 | trans->transid, root->fs_info->generation); | 
| 1429 | (unsigned long long)root->fs_info->generation); | ||
| 1430 | 1390 | ||
| 1431 | if (!should_cow_block(trans, root, buf)) { | 1391 | if (!should_cow_block(trans, root, buf)) { | 
| 1432 | *cow_ret = buf; | 1392 | *cow_ret = buf; | 
| @@ -2466,6 +2426,40 @@ done: | |||
| 2466 | return ret; | 2426 | return ret; | 
| 2467 | } | 2427 | } | 
| 2468 | 2428 | ||
| 2429 | static void key_search_validate(struct extent_buffer *b, | ||
| 2430 | struct btrfs_key *key, | ||
| 2431 | int level) | ||
| 2432 | { | ||
| 2433 | #ifdef CONFIG_BTRFS_ASSERT | ||
| 2434 | struct btrfs_disk_key disk_key; | ||
| 2435 | |||
| 2436 | btrfs_cpu_key_to_disk(&disk_key, key); | ||
| 2437 | |||
| 2438 | if (level == 0) | ||
| 2439 | ASSERT(!memcmp_extent_buffer(b, &disk_key, | ||
| 2440 | offsetof(struct btrfs_leaf, items[0].key), | ||
| 2441 | sizeof(disk_key))); | ||
| 2442 | else | ||
| 2443 | ASSERT(!memcmp_extent_buffer(b, &disk_key, | ||
| 2444 | offsetof(struct btrfs_node, ptrs[0].key), | ||
| 2445 | sizeof(disk_key))); | ||
| 2446 | #endif | ||
| 2447 | } | ||
| 2448 | |||
| 2449 | static int key_search(struct extent_buffer *b, struct btrfs_key *key, | ||
| 2450 | int level, int *prev_cmp, int *slot) | ||
| 2451 | { | ||
| 2452 | if (*prev_cmp != 0) { | ||
| 2453 | *prev_cmp = bin_search(b, key, level, slot); | ||
| 2454 | return *prev_cmp; | ||
| 2455 | } | ||
| 2456 | |||
| 2457 | key_search_validate(b, key, level); | ||
| 2458 | *slot = 0; | ||
| 2459 | |||
| 2460 | return 0; | ||
| 2461 | } | ||
| 2462 | |||
| 2469 | /* | 2463 | /* | 
| 2470 | * look for key in the tree. path is filled in with nodes along the way | 2464 | * look for key in the tree. path is filled in with nodes along the way | 
| 2471 | * if key is found, we return zero and you can find the item in the leaf | 2465 | * if key is found, we return zero and you can find the item in the leaf | 
| @@ -2494,6 +2488,7 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 2494 | int write_lock_level = 0; | 2488 | int write_lock_level = 0; | 
| 2495 | u8 lowest_level = 0; | 2489 | u8 lowest_level = 0; | 
| 2496 | int min_write_lock_level; | 2490 | int min_write_lock_level; | 
| 2491 | int prev_cmp; | ||
| 2497 | 2492 | ||
| 2498 | lowest_level = p->lowest_level; | 2493 | lowest_level = p->lowest_level; | 
| 2499 | WARN_ON(lowest_level && ins_len > 0); | 2494 | WARN_ON(lowest_level && ins_len > 0); | 
| @@ -2524,6 +2519,7 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 2524 | min_write_lock_level = write_lock_level; | 2519 | min_write_lock_level = write_lock_level; | 
| 2525 | 2520 | ||
| 2526 | again: | 2521 | again: | 
| 2522 | prev_cmp = -1; | ||
| 2527 | /* | 2523 | /* | 
| 2528 | * we try very hard to do read locks on the root | 2524 | * we try very hard to do read locks on the root | 
| 2529 | */ | 2525 | */ | 
| @@ -2624,7 +2620,7 @@ cow_done: | |||
| 2624 | if (!cow) | 2620 | if (!cow) | 
| 2625 | btrfs_unlock_up_safe(p, level + 1); | 2621 | btrfs_unlock_up_safe(p, level + 1); | 
| 2626 | 2622 | ||
| 2627 | ret = bin_search(b, key, level, &slot); | 2623 | ret = key_search(b, key, level, &prev_cmp, &slot); | 
| 2628 | 2624 | ||
| 2629 | if (level != 0) { | 2625 | if (level != 0) { | 
| 2630 | int dec = 0; | 2626 | int dec = 0; | 
| @@ -2759,6 +2755,7 @@ int btrfs_search_old_slot(struct btrfs_root *root, struct btrfs_key *key, | |||
| 2759 | int level; | 2755 | int level; | 
| 2760 | int lowest_unlock = 1; | 2756 | int lowest_unlock = 1; | 
| 2761 | u8 lowest_level = 0; | 2757 | u8 lowest_level = 0; | 
| 2758 | int prev_cmp; | ||
| 2762 | 2759 | ||
| 2763 | lowest_level = p->lowest_level; | 2760 | lowest_level = p->lowest_level; | 
| 2764 | WARN_ON(p->nodes[0] != NULL); | 2761 | WARN_ON(p->nodes[0] != NULL); | 
| @@ -2769,6 +2766,7 @@ int btrfs_search_old_slot(struct btrfs_root *root, struct btrfs_key *key, | |||
| 2769 | } | 2766 | } | 
| 2770 | 2767 | ||
| 2771 | again: | 2768 | again: | 
| 2769 | prev_cmp = -1; | ||
| 2772 | b = get_old_root(root, time_seq); | 2770 | b = get_old_root(root, time_seq); | 
| 2773 | level = btrfs_header_level(b); | 2771 | level = btrfs_header_level(b); | 
| 2774 | p->locks[level] = BTRFS_READ_LOCK; | 2772 | p->locks[level] = BTRFS_READ_LOCK; | 
| @@ -2786,7 +2784,7 @@ again: | |||
| 2786 | */ | 2784 | */ | 
| 2787 | btrfs_unlock_up_safe(p, level + 1); | 2785 | btrfs_unlock_up_safe(p, level + 1); | 
| 2788 | 2786 | ||
| 2789 | ret = bin_search(b, key, level, &slot); | 2787 | ret = key_search(b, key, level, &prev_cmp, &slot); | 
| 2790 | 2788 | ||
| 2791 | if (level != 0) { | 2789 | if (level != 0) { | 
| 2792 | int dec = 0; | 2790 | int dec = 0; | 
| @@ -2820,7 +2818,11 @@ again: | |||
| 2820 | btrfs_clear_path_blocking(p, b, | 2818 | btrfs_clear_path_blocking(p, b, | 
| 2821 | BTRFS_READ_LOCK); | 2819 | BTRFS_READ_LOCK); | 
| 2822 | } | 2820 | } | 
| 2823 | b = tree_mod_log_rewind(root->fs_info, b, time_seq); | 2821 | b = tree_mod_log_rewind(root->fs_info, p, b, time_seq); | 
| 2822 | if (!b) { | ||
| 2823 | ret = -ENOMEM; | ||
| 2824 | goto done; | ||
| 2825 | } | ||
| 2824 | p->locks[level] = BTRFS_READ_LOCK; | 2826 | p->locks[level] = BTRFS_READ_LOCK; | 
| 2825 | p->nodes[level] = b; | 2827 | p->nodes[level] = b; | 
| 2826 | } else { | 2828 | } else { | 
| @@ -3143,13 +3145,11 @@ static noinline int insert_new_root(struct btrfs_trans_handle *trans, | |||
| 3143 | btrfs_set_header_backref_rev(c, BTRFS_MIXED_BACKREF_REV); | 3145 | btrfs_set_header_backref_rev(c, BTRFS_MIXED_BACKREF_REV); | 
| 3144 | btrfs_set_header_owner(c, root->root_key.objectid); | 3146 | btrfs_set_header_owner(c, root->root_key.objectid); | 
| 3145 | 3147 | ||
| 3146 | write_extent_buffer(c, root->fs_info->fsid, | 3148 | write_extent_buffer(c, root->fs_info->fsid, btrfs_header_fsid(c), | 
| 3147 | (unsigned long)btrfs_header_fsid(c), | ||
| 3148 | BTRFS_FSID_SIZE); | 3149 | BTRFS_FSID_SIZE); | 
| 3149 | 3150 | ||
| 3150 | write_extent_buffer(c, root->fs_info->chunk_tree_uuid, | 3151 | write_extent_buffer(c, root->fs_info->chunk_tree_uuid, | 
| 3151 | (unsigned long)btrfs_header_chunk_tree_uuid(c), | 3152 | btrfs_header_chunk_tree_uuid(c), BTRFS_UUID_SIZE); | 
| 3152 | BTRFS_UUID_SIZE); | ||
| 3153 | 3153 | ||
| 3154 | btrfs_set_node_key(c, &lower_key, 0); | 3154 | btrfs_set_node_key(c, &lower_key, 0); | 
| 3155 | btrfs_set_node_blockptr(c, 0, lower->start); | 3155 | btrfs_set_node_blockptr(c, 0, lower->start); | 
| @@ -3208,7 +3208,7 @@ static void insert_ptr(struct btrfs_trans_handle *trans, | |||
| 3208 | } | 3208 | } | 
| 3209 | if (level) { | 3209 | if (level) { | 
| 3210 | ret = tree_mod_log_insert_key(root->fs_info, lower, slot, | 3210 | ret = tree_mod_log_insert_key(root->fs_info, lower, slot, | 
| 3211 | MOD_LOG_KEY_ADD); | 3211 | MOD_LOG_KEY_ADD, GFP_NOFS); | 
| 3212 | BUG_ON(ret < 0); | 3212 | BUG_ON(ret < 0); | 
| 3213 | } | 3213 | } | 
| 3214 | btrfs_set_node_key(lower, key, slot); | 3214 | btrfs_set_node_key(lower, key, slot); | 
| @@ -3284,10 +3284,9 @@ static noinline int split_node(struct btrfs_trans_handle *trans, | |||
| 3284 | btrfs_set_header_backref_rev(split, BTRFS_MIXED_BACKREF_REV); | 3284 | btrfs_set_header_backref_rev(split, BTRFS_MIXED_BACKREF_REV); | 
| 3285 | btrfs_set_header_owner(split, root->root_key.objectid); | 3285 | btrfs_set_header_owner(split, root->root_key.objectid); | 
| 3286 | write_extent_buffer(split, root->fs_info->fsid, | 3286 | write_extent_buffer(split, root->fs_info->fsid, | 
| 3287 | (unsigned long)btrfs_header_fsid(split), | 3287 | btrfs_header_fsid(split), BTRFS_FSID_SIZE); | 
| 3288 | BTRFS_FSID_SIZE); | ||
| 3289 | write_extent_buffer(split, root->fs_info->chunk_tree_uuid, | 3288 | write_extent_buffer(split, root->fs_info->chunk_tree_uuid, | 
| 3290 | (unsigned long)btrfs_header_chunk_tree_uuid(split), | 3289 | btrfs_header_chunk_tree_uuid(split), | 
| 3291 | BTRFS_UUID_SIZE); | 3290 | BTRFS_UUID_SIZE); | 
| 3292 | 3291 | ||
| 3293 | tree_mod_log_eb_copy(root->fs_info, split, c, 0, mid, c_nritems - mid); | 3292 | tree_mod_log_eb_copy(root->fs_info, split, c, 0, mid, c_nritems - mid); | 
| @@ -4040,11 +4039,10 @@ again: | |||
| 4040 | btrfs_set_header_owner(right, root->root_key.objectid); | 4039 | btrfs_set_header_owner(right, root->root_key.objectid); | 
| 4041 | btrfs_set_header_level(right, 0); | 4040 | btrfs_set_header_level(right, 0); | 
| 4042 | write_extent_buffer(right, root->fs_info->fsid, | 4041 | write_extent_buffer(right, root->fs_info->fsid, | 
| 4043 | (unsigned long)btrfs_header_fsid(right), | 4042 | btrfs_header_fsid(right), BTRFS_FSID_SIZE); | 
| 4044 | BTRFS_FSID_SIZE); | ||
| 4045 | 4043 | ||
| 4046 | write_extent_buffer(right, root->fs_info->chunk_tree_uuid, | 4044 | write_extent_buffer(right, root->fs_info->chunk_tree_uuid, | 
| 4047 | (unsigned long)btrfs_header_chunk_tree_uuid(right), | 4045 | btrfs_header_chunk_tree_uuid(right), | 
| 4048 | BTRFS_UUID_SIZE); | 4046 | BTRFS_UUID_SIZE); | 
| 4049 | 4047 | ||
| 4050 | if (split == 0) { | 4048 | if (split == 0) { | 
| @@ -4642,7 +4640,7 @@ static void del_ptr(struct btrfs_root *root, struct btrfs_path *path, | |||
| 4642 | (nritems - slot - 1)); | 4640 | (nritems - slot - 1)); | 
| 4643 | } else if (level) { | 4641 | } else if (level) { | 
| 4644 | ret = tree_mod_log_insert_key(root->fs_info, parent, slot, | 4642 | ret = tree_mod_log_insert_key(root->fs_info, parent, slot, | 
| 4645 | MOD_LOG_KEY_REMOVE); | 4643 | MOD_LOG_KEY_REMOVE, GFP_NOFS); | 
| 4646 | BUG_ON(ret < 0); | 4644 | BUG_ON(ret < 0); | 
| 4647 | } | 4645 | } | 
| 4648 | 4646 | ||
| @@ -4814,7 +4812,7 @@ int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
| 4814 | * This may release the path, and so you may lose any locks held at the | 4812 | * This may release the path, and so you may lose any locks held at the | 
| 4815 | * time you call it. | 4813 | * time you call it. | 
| 4816 | */ | 4814 | */ | 
| 4817 | int btrfs_prev_leaf(struct btrfs_root *root, struct btrfs_path *path) | 4815 | static int btrfs_prev_leaf(struct btrfs_root *root, struct btrfs_path *path) | 
| 4818 | { | 4816 | { | 
| 4819 | struct btrfs_key key; | 4817 | struct btrfs_key key; | 
| 4820 | struct btrfs_disk_key found_key; | 4818 | struct btrfs_disk_key found_key; | 
| @@ -5329,19 +5327,20 @@ int btrfs_compare_trees(struct btrfs_root *left_root, | |||
| 5329 | goto out; | 5327 | goto out; | 
| 5330 | advance_right = ADVANCE; | 5328 | advance_right = ADVANCE; | 
| 5331 | } else { | 5329 | } else { | 
| 5330 | enum btrfs_compare_tree_result cmp; | ||
| 5331 | |||
| 5332 | WARN_ON(!extent_buffer_uptodate(left_path->nodes[0])); | 5332 | WARN_ON(!extent_buffer_uptodate(left_path->nodes[0])); | 
| 5333 | ret = tree_compare_item(left_root, left_path, | 5333 | ret = tree_compare_item(left_root, left_path, | 
| 5334 | right_path, tmp_buf); | 5334 | right_path, tmp_buf); | 
| 5335 | if (ret) { | 5335 | if (ret) | 
| 5336 | WARN_ON(!extent_buffer_uptodate(left_path->nodes[0])); | 5336 | cmp = BTRFS_COMPARE_TREE_CHANGED; | 
| 5337 | ret = changed_cb(left_root, right_root, | 5337 | else | 
| 5338 | left_path, right_path, | 5338 | cmp = BTRFS_COMPARE_TREE_SAME; | 
| 5339 | &left_key, | 5339 | ret = changed_cb(left_root, right_root, | 
| 5340 | BTRFS_COMPARE_TREE_CHANGED, | 5340 | left_path, right_path, | 
| 5341 | ctx); | 5341 | &left_key, cmp, ctx); | 
| 5342 | if (ret < 0) | 5342 | if (ret < 0) | 
| 5343 | goto out; | 5343 | goto out; | 
| 5344 | } | ||
| 5345 | advance_left = ADVANCE; | 5344 | advance_left = ADVANCE; | 
| 5346 | advance_right = ADVANCE; | 5345 | advance_right = ADVANCE; | 
| 5347 | } | 5346 | } | 
