diff options
| -rw-r--r-- | fs/reiserfs/do_balan.c | 290 |
1 files changed, 165 insertions, 125 deletions
diff --git a/fs/reiserfs/do_balan.c b/fs/reiserfs/do_balan.c index fcebfca0bbb8..793fab7b9f02 100644 --- a/fs/reiserfs/do_balan.c +++ b/fs/reiserfs/do_balan.c | |||
| @@ -706,155 +706,197 @@ static void balance_leaf_insert_right(struct tree_balance *tb, | |||
| 706 | } | 706 | } |
| 707 | } | 707 | } |
| 708 | 708 | ||
| 709 | static void balance_leaf_paste_right(struct tree_balance *tb, | 709 | |
| 710 | static void balance_leaf_paste_right_shift_dirent(struct tree_balance *tb, | ||
| 710 | struct item_head *ih, const char *body) | 711 | struct item_head *ih, const char *body) |
| 711 | { | 712 | { |
| 712 | struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path); | 713 | struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path); |
| 713 | int n = B_NR_ITEMS(tbS0); | ||
| 714 | struct buffer_info bi; | 714 | struct buffer_info bi; |
| 715 | int ret_val; | 715 | int entry_count; |
| 716 | 716 | ||
| 717 | if (n - tb->rnum[0] <= tb->item_pos) { /* pasted item or part of it falls to R[0] */ | 717 | RFALSE(zeroes_num, |
| 718 | if (tb->item_pos == n - tb->rnum[0] && tb->rbytes != -1) { /* we must shift the part of the appended item */ | 718 | "PAP-12145: invalid parameter in case of a directory"); |
| 719 | if (is_direntry_le_ih(item_head(tbS0, tb->item_pos))) { /* we append to directory item */ | 719 | entry_count = ih_entry_count(item_head(tbS0, tb->item_pos)); |
| 720 | int entry_count; | ||
| 721 | 720 | ||
| 722 | RFALSE(tb->zeroes_num, | 721 | /* new directory entry falls into R[0] */ |
| 723 | "PAP-12145: invalid parameter in case of a directory"); | 722 | if (entry_count - tb->rbytes < tb->pos_in_item) { |
| 724 | entry_count = ih_entry_count(item_head | 723 | int paste_entry_position; |
| 725 | (tbS0, tb->item_pos)); | ||
| 726 | if (entry_count - tb->rbytes < | ||
| 727 | tb->pos_in_item) | ||
| 728 | /* new directory entry falls into R[0] */ | ||
| 729 | { | ||
| 730 | int paste_entry_position; | ||
| 731 | 724 | ||
| 732 | RFALSE(tb->rbytes - 1 >= entry_count || !tb-> insert_size[0], | 725 | RFALSE(tb->rbytes - 1 >= entry_count || !tb->insert_size[0], |
| 733 | "PAP-12150: no enough of entries to shift to R[0]: rbytes=%d, entry_count=%d", | 726 | "PAP-12150: no enough of entries to shift to R[0]: " |
| 734 | tb->rbytes, entry_count); | 727 | "rbytes=%d, entry_count=%d", tb->rbytes, entry_count); |
| 735 | /* Shift rnum[0]-1 items in whole. Shift rbytes-1 directory entries from directory item number rnum[0] */ | ||
| 736 | leaf_shift_right(tb, tb->rnum[0], tb->rbytes - 1); | ||
| 737 | /* Paste given directory entry to directory item */ | ||
| 738 | paste_entry_position = tb->pos_in_item - entry_count + tb->rbytes - 1; | ||
| 739 | buffer_info_init_right(tb, &bi); | ||
| 740 | leaf_paste_in_buffer(&bi, 0, paste_entry_position, tb->insert_size[0], body, tb->zeroes_num); | ||
| 741 | /* paste entry */ | ||
| 742 | leaf_paste_entries(&bi, 0, paste_entry_position, 1, | ||
| 743 | (struct reiserfs_de_head *) body, | ||
| 744 | body + DEH_SIZE, tb->insert_size[0]); | ||
| 745 | 728 | ||
| 746 | if (paste_entry_position == 0) { | 729 | /* |
| 747 | /* change delimiting keys */ | 730 | * Shift rnum[0]-1 items in whole. |
| 748 | replace_key(tb, tb->CFR[0], tb->rkey[0], tb->R[0],0); | 731 | * Shift rbytes-1 directory entries from directory |
| 749 | } | 732 | * item number rnum[0] |
| 733 | */ | ||
| 734 | leaf_shift_right(tb, tb->rnum[0], tb->rbytes - 1); | ||
| 750 | 735 | ||
| 751 | tb->insert_size[0] = 0; | 736 | /* Paste given directory entry to directory item */ |
| 752 | tb->pos_in_item++; | 737 | paste_entry_position = tb->pos_in_item - entry_count + |
| 753 | } else { /* new directory entry doesn't fall into R[0] */ | 738 | tb->rbytes - 1; |
| 739 | buffer_info_init_right(tb, &bi); | ||
| 740 | leaf_paste_in_buffer(&bi, 0, paste_entry_position, | ||
| 741 | tb->insert_size[0], body, tb->zeroes_num); | ||
| 754 | 742 | ||
| 755 | leaf_shift_right(tb, tb->rnum[0], tb->rbytes); | 743 | /* paste entry */ |
| 756 | } | 744 | leaf_paste_entries(&bi, 0, paste_entry_position, 1, |
| 757 | } else { /* regular object */ | 745 | (struct reiserfs_de_head *) body, |
| 746 | body + DEH_SIZE, tb->insert_size[0]); | ||
| 758 | 747 | ||
| 759 | int n_shift, n_rem, r_zeroes_number; | 748 | /* change delimiting keys */ |
| 760 | const char *r_body; | 749 | if (paste_entry_position == 0) |
| 750 | replace_key(tb, tb->CFR[0], tb->rkey[0], tb->R[0], 0); | ||
| 761 | 751 | ||
| 762 | /* Calculate number of bytes which must be shifted from appended item */ | 752 | tb->insert_size[0] = 0; |
| 763 | if ((n_shift = tb->rbytes - tb->insert_size[0]) < 0) | 753 | tb->pos_in_item++; |
| 764 | n_shift = 0; | 754 | } else { |
| 755 | /* new directory entry doesn't fall into R[0] */ | ||
| 756 | leaf_shift_right(tb, tb->rnum[0], tb->rbytes); | ||
| 757 | } | ||
| 758 | } | ||
| 765 | 759 | ||
| 766 | RFALSE(tb->pos_in_item != ih_item_len | 760 | static void balance_leaf_paste_right_shift(struct tree_balance *tb, |
| 767 | (item_head(tbS0, tb->item_pos)), | 761 | struct item_head *ih, const char *body) |
| 768 | "PAP-12155: invalid position to paste. ih_item_len=%d, pos_in_item=%d", | 762 | { |
| 769 | tb->pos_in_item, ih_item_len | 763 | struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path); |
| 770 | (item_head(tbS0, tb->item_pos))); | 764 | int n_shift, n_rem, r_zeroes_number, version; |
| 765 | unsigned long temp_rem; | ||
| 766 | const char *r_body; | ||
| 767 | struct buffer_info bi; | ||
| 771 | 768 | ||
| 772 | leaf_shift_right(tb, tb->rnum[0], n_shift); | 769 | /* we append to directory item */ |
| 773 | /* Calculate number of bytes which must remain in body after appending to R[0] */ | 770 | if (is_direntry_le_ih(item_head(tbS0, tb->item_pos))) { |
| 774 | if ((n_rem = tb->insert_size[0] - tb->rbytes) < 0) | 771 | balance_leaf_paste_right_shift_dirent(tb, ih, body); |
| 775 | n_rem = 0; | 772 | return; |
| 773 | } | ||
| 776 | 774 | ||
| 777 | { | 775 | /* regular object */ |
| 778 | int version; | ||
| 779 | unsigned long temp_rem = n_rem; | ||
| 780 | 776 | ||
| 781 | version = ih_version(item_head(tb->R[0], 0)); | 777 | /* |
| 782 | if (is_indirect_le_key(version, leaf_key(tb->R[0], 0))) { | 778 | * Calculate number of bytes which must be shifted |
| 783 | temp_rem = n_rem << (tb->tb_sb->s_blocksize_bits - UNFM_P_SHIFT); | 779 | * from appended item |
| 784 | } | 780 | */ |
| 785 | set_le_key_k_offset(version, leaf_key(tb->R[0], 0), | 781 | n_shift = tb->rbytes - tb->insert_size[0]; |
| 786 | le_key_k_offset(version, leaf_key(tb->R[0], 0)) + temp_rem); | 782 | if (n_shift < 0) |
| 787 | set_le_key_k_offset(version, internal_key(tb->CFR[0], tb->rkey[0]), | 783 | n_shift = 0; |
| 788 | le_key_k_offset(version, internal_key(tb->CFR[0], tb->rkey[0])) + temp_rem); | ||
| 789 | } | ||
| 790 | /* k_offset (leaf_key(tb->R[0],0)) += n_rem; | ||
| 791 | k_offset (internal_key(tb->CFR[0],tb->rkey[0])) += n_rem;*/ | ||
| 792 | do_balance_mark_internal_dirty(tb, tb->CFR[0], 0); | ||
| 793 | 784 | ||
| 794 | /* Append part of body into R[0] */ | 785 | RFALSE(pos_in_item != ih_item_len(item_head(tbS0, item_pos)), |
| 795 | buffer_info_init_right(tb, &bi); | 786 | "PAP-12155: invalid position to paste. ih_item_len=%d, " |
| 796 | if (n_rem > tb->zeroes_num) { | 787 | "pos_in_item=%d", pos_in_item, |
| 797 | r_zeroes_number = 0; | 788 | ih_item_len(item_head(tbS0, item_pos))); |
| 798 | r_body = body + n_rem - tb->zeroes_num; | ||
| 799 | } else { | ||
| 800 | r_body = body; | ||
| 801 | r_zeroes_number = tb->zeroes_num - n_rem; | ||
| 802 | tb->zeroes_num -= r_zeroes_number; | ||
| 803 | } | ||
| 804 | 789 | ||
| 805 | leaf_paste_in_buffer(&bi, 0, n_shift, | 790 | leaf_shift_right(tb, tb->rnum[0], n_shift); |
| 806 | tb->insert_size[0] - n_rem, | ||
| 807 | r_body, r_zeroes_number); | ||
| 808 | 791 | ||
| 809 | if (is_indirect_le_ih(item_head(tb->R[0], 0))) { | 792 | /* |
| 810 | #if 0 | 793 | * Calculate number of bytes which must remain in body |
| 811 | RFALSE(n_rem, | 794 | * after appending to R[0] |
| 812 | "PAP-12160: paste more than one unformatted node pointer"); | 795 | */ |
| 813 | #endif | 796 | n_rem = tb->insert_size[0] - tb->rbytes; |
| 814 | set_ih_free_space(item_head(tb->R[0], 0), 0); | 797 | if (n_rem < 0) |
| 815 | } | 798 | n_rem = 0; |
| 816 | tb->insert_size[0] = n_rem; | ||
| 817 | if (!n_rem) | ||
| 818 | tb->pos_in_item++; | ||
| 819 | } | ||
| 820 | } else { /* pasted item in whole falls into R[0] */ | ||
| 821 | 799 | ||
| 822 | struct item_head *pasted; | 800 | temp_rem = n_rem; |
| 823 | 801 | ||
| 824 | ret_val = leaf_shift_right(tb, tb->rnum[0], tb->rbytes); | 802 | version = ih_version(item_head(tb->R[0], 0)); |
| 825 | /* append item in R[0] */ | ||
| 826 | if (tb->pos_in_item >= 0) { | ||
| 827 | buffer_info_init_right(tb, &bi); | ||
| 828 | leaf_paste_in_buffer(&bi, tb->item_pos - n + tb->rnum[0], tb->pos_in_item, | ||
| 829 | tb->insert_size[0], body, tb->zeroes_num); | ||
| 830 | } | ||
| 831 | 803 | ||
| 832 | /* paste new entry, if item is directory item */ | 804 | if (is_indirect_le_key(version, leaf_key(tb->R[0], 0))) { |
| 833 | pasted = item_head(tb->R[0], tb->item_pos - n + tb->rnum[0]); | 805 | int shift = tb->tb_sb->s_blocksize_bits - UNFM_P_SHIFT; |
| 834 | if (is_direntry_le_ih(pasted) && tb->pos_in_item >= 0) { | 806 | temp_rem = n_rem << shift; |
| 835 | leaf_paste_entries(&bi, tb->item_pos - n + tb->rnum[0], | 807 | } |
| 836 | tb->pos_in_item, 1, | ||
| 837 | (struct reiserfs_de_head *) body, | ||
| 838 | body + DEH_SIZE, tb->insert_size[0]); | ||
| 839 | if (!tb->pos_in_item) { | ||
| 840 | 808 | ||
| 841 | RFALSE(tb->item_pos - n + tb->rnum[0], | 809 | add_le_key_k_offset(version, leaf_key(tb->R[0], 0), temp_rem); |
| 842 | "PAP-12165: directory item must be first item of node when pasting is in 0th position"); | 810 | add_le_key_k_offset(version, internal_key(tb->CFR[0], tb->rkey[0]), |
| 811 | temp_rem); | ||
| 843 | 812 | ||
| 844 | /* update delimiting keys */ | 813 | do_balance_mark_internal_dirty(tb, tb->CFR[0], 0); |
| 845 | replace_key(tb, tb->CFR[0], tb->rkey[0], tb->R[0], 0); | ||
| 846 | } | ||
| 847 | } | ||
| 848 | 814 | ||
| 849 | if (is_indirect_le_ih(pasted)) | 815 | /* Append part of body into R[0] */ |
| 850 | set_ih_free_space(pasted, 0); | 816 | buffer_info_init_right(tb, &bi); |
| 851 | tb->zeroes_num = tb->insert_size[0] = 0; | 817 | if (n_rem > tb->zeroes_num) { |
| 852 | } | 818 | r_zeroes_number = 0; |
| 853 | } else { /* new item doesn't fall into R[0] */ | 819 | r_body = body + n_rem - tb->zeroes_num; |
| 820 | } else { | ||
| 821 | r_body = body; | ||
| 822 | r_zeroes_number = tb->zeroes_num - n_rem; | ||
| 823 | tb->zeroes_num -= r_zeroes_number; | ||
| 824 | } | ||
| 854 | 825 | ||
| 855 | leaf_shift_right(tb, tb->rnum[0], tb->rbytes); | 826 | leaf_paste_in_buffer(&bi, 0, n_shift, tb->insert_size[0] - n_rem, |
| 856 | } | 827 | r_body, r_zeroes_number); |
| 828 | |||
| 829 | if (is_indirect_le_ih(item_head(tb->R[0], 0))) | ||
| 830 | set_ih_free_space(item_head(tb->R[0], 0), 0); | ||
| 831 | |||
| 832 | tb->insert_size[0] = n_rem; | ||
| 833 | if (!n_rem) | ||
| 834 | tb->pos_in_item++; | ||
| 835 | } | ||
| 836 | |||
| 837 | static void balance_leaf_paste_right_whole(struct tree_balance *tb, | ||
| 838 | struct item_head *ih, const char *body) | ||
| 839 | { | ||
| 840 | struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path); | ||
| 841 | int n = B_NR_ITEMS(tbS0); | ||
| 842 | struct item_head *pasted; | ||
| 843 | struct buffer_info bi; | ||
| 844 | |||
| 845 | buffer_info_init_right(tb, &bi); | ||
| 846 | leaf_shift_right(tb, tb->rnum[0], tb->rbytes); | ||
| 847 | |||
| 848 | /* append item in R[0] */ | ||
| 849 | if (tb->pos_in_item >= 0) { | ||
| 850 | buffer_info_init_right(tb, &bi); | ||
| 851 | leaf_paste_in_buffer(&bi, tb->item_pos - n + tb->rnum[0], | ||
| 852 | tb->pos_in_item, tb->insert_size[0], body, | ||
| 853 | tb->zeroes_num); | ||
| 854 | } | ||
| 855 | |||
| 856 | /* paste new entry, if item is directory item */ | ||
| 857 | pasted = item_head(tb->R[0], tb->item_pos - n + tb->rnum[0]); | ||
| 858 | if (is_direntry_le_ih(pasted) && tb->pos_in_item >= 0) { | ||
| 859 | leaf_paste_entries(&bi, tb->item_pos - n + tb->rnum[0], | ||
| 860 | tb->pos_in_item, 1, | ||
| 861 | (struct reiserfs_de_head *)body, | ||
| 862 | body + DEH_SIZE, tb->insert_size[0]); | ||
| 863 | |||
| 864 | if (!tb->pos_in_item) { | ||
| 865 | |||
| 866 | RFALSE(tb->item_pos - n + tb->rnum[0], | ||
| 867 | "PAP-12165: directory item must be first " | ||
| 868 | "item of node when pasting is in 0th position"); | ||
| 869 | |||
| 870 | /* update delimiting keys */ | ||
| 871 | replace_key(tb, tb->CFR[0], tb->rkey[0], tb->R[0], 0); | ||
| 872 | } | ||
| 873 | } | ||
| 874 | |||
| 875 | if (is_indirect_le_ih(pasted)) | ||
| 876 | set_ih_free_space(pasted, 0); | ||
| 877 | tb->zeroes_num = tb->insert_size[0] = 0; | ||
| 878 | } | ||
| 879 | |||
| 880 | static void balance_leaf_paste_right(struct tree_balance *tb, | ||
| 881 | struct item_head *ih, const char *body) | ||
| 882 | { | ||
| 883 | struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path); | ||
| 884 | int n = B_NR_ITEMS(tbS0); | ||
| 857 | 885 | ||
| 886 | /* new item doesn't fall into R[0] */ | ||
| 887 | if (n - tb->rnum[0] > tb->item_pos) { | ||
| 888 | leaf_shift_right(tb, tb->rnum[0], tb->rbytes); | ||
| 889 | return; | ||
| 890 | } | ||
| 891 | |||
| 892 | /* pasted item or part of it falls to R[0] */ | ||
| 893 | |||
| 894 | if (tb->item_pos == n - tb->rnum[0] && tb->rbytes != -1) | ||
| 895 | /* we must shift the part of the appended item */ | ||
| 896 | balance_leaf_paste_right_shift(tb, ih, body); | ||
| 897 | else | ||
| 898 | /* pasted item in whole falls into R[0] */ | ||
| 899 | balance_leaf_paste_right_whole(tb, ih, body); | ||
| 858 | } | 900 | } |
| 859 | 901 | ||
| 860 | /* shift rnum[0] items from S[0] to the right neighbor R[0] */ | 902 | /* shift rnum[0] items from S[0] to the right neighbor R[0] */ |
| @@ -870,7 +912,6 @@ static void balance_leaf_right(struct tree_balance *tb, struct item_head *ih, | |||
| 870 | balance_leaf_insert_right(tb, ih, body); | 912 | balance_leaf_insert_right(tb, ih, body); |
| 871 | else /* M_PASTE */ | 913 | else /* M_PASTE */ |
| 872 | balance_leaf_paste_right(tb, ih, body); | 914 | balance_leaf_paste_right(tb, ih, body); |
| 873 | |||
| 874 | } | 915 | } |
| 875 | 916 | ||
| 876 | static void balance_leaf_new_nodes_insert(struct tree_balance *tb, | 917 | static void balance_leaf_new_nodes_insert(struct tree_balance *tb, |
| @@ -1083,8 +1124,7 @@ static void balance_leaf_new_nodes_paste(struct tree_balance *tb, | |||
| 1083 | tb->pos_in_item, 1, | 1124 | tb->pos_in_item, 1, |
| 1084 | (struct reiserfs_de_head *)body, | 1125 | (struct reiserfs_de_head *)body, |
| 1085 | body + DEH_SIZE, | 1126 | body + DEH_SIZE, |
| 1086 | tb->insert_size[0] | 1127 | tb->insert_size[0]); |
| 1087 | ); | ||
| 1088 | } | 1128 | } |
| 1089 | 1129 | ||
| 1090 | /* if we paste to indirect item update ih_free_space */ | 1130 | /* if we paste to indirect item update ih_free_space */ |
