diff options
| -rw-r--r-- | fs/reiserfs/do_balan.c | 476 |
1 files changed, 271 insertions, 205 deletions
diff --git a/fs/reiserfs/do_balan.c b/fs/reiserfs/do_balan.c index 793fab7b9f02..cffcb67a5436 100644 --- a/fs/reiserfs/do_balan.c +++ b/fs/reiserfs/do_balan.c | |||
| @@ -714,7 +714,7 @@ static void balance_leaf_paste_right_shift_dirent(struct tree_balance *tb, | |||
| 714 | struct buffer_info bi; | 714 | struct buffer_info bi; |
| 715 | int entry_count; | 715 | int entry_count; |
| 716 | 716 | ||
| 717 | RFALSE(zeroes_num, | 717 | RFALSE(tb->zeroes_num, |
| 718 | "PAP-12145: invalid parameter in case of a directory"); | 718 | "PAP-12145: invalid parameter in case of a directory"); |
| 719 | entry_count = ih_entry_count(item_head(tbS0, tb->item_pos)); | 719 | entry_count = ih_entry_count(item_head(tbS0, tb->item_pos)); |
| 720 | 720 | ||
| @@ -782,10 +782,10 @@ static void balance_leaf_paste_right_shift(struct tree_balance *tb, | |||
| 782 | if (n_shift < 0) | 782 | if (n_shift < 0) |
| 783 | n_shift = 0; | 783 | n_shift = 0; |
| 784 | 784 | ||
| 785 | RFALSE(pos_in_item != ih_item_len(item_head(tbS0, item_pos)), | 785 | RFALSE(tb->pos_in_item != ih_item_len(item_head(tbS0, tb->item_pos)), |
| 786 | "PAP-12155: invalid position to paste. ih_item_len=%d, " | 786 | "PAP-12155: invalid position to paste. ih_item_len=%d, " |
| 787 | "pos_in_item=%d", pos_in_item, | 787 | "pos_in_item=%d", tb->pos_in_item, |
| 788 | ih_item_len(item_head(tbS0, item_pos))); | 788 | ih_item_len(item_head(tbS0, tb->item_pos))); |
| 789 | 789 | ||
| 790 | leaf_shift_right(tb, tb->rnum[0], n_shift); | 790 | leaf_shift_right(tb, tb->rnum[0], n_shift); |
| 791 | 791 | ||
| @@ -924,68 +924,89 @@ static void balance_leaf_new_nodes_insert(struct tree_balance *tb, | |||
| 924 | struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path); | 924 | struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path); |
| 925 | int n = B_NR_ITEMS(tbS0); | 925 | int n = B_NR_ITEMS(tbS0); |
| 926 | struct buffer_info bi; | 926 | struct buffer_info bi; |
| 927 | if (n - tb->snum[i] < tb->item_pos) { /* new item or it's part falls to first new node S_new[i] */ | 927 | int shift; |
| 928 | if (tb->item_pos == n - tb->snum[i] + 1 && tb->sbytes[i] != -1) { /* part of new item falls into S_new[i] */ | ||
| 929 | int old_key_comp, old_len, r_zeroes_number; | ||
| 930 | const char *r_body; | ||
| 931 | int version; | ||
| 932 | |||
| 933 | /* Move snum[i]-1 items from S[0] to S_new[i] */ | ||
| 934 | leaf_move_items(LEAF_FROM_S_TO_SNEW, tb, | ||
| 935 | tb->snum[i] - 1, -1, | ||
| 936 | tb->S_new[i]); | ||
| 937 | /* Remember key component and item length */ | ||
| 938 | version = ih_version(ih); | ||
| 939 | old_key_comp = le_ih_k_offset(ih); | ||
| 940 | old_len = ih_item_len(ih); | ||
| 941 | |||
| 942 | /* Calculate key component and item length to insert into S_new[i] */ | ||
| 943 | set_le_ih_k_offset(ih, le_ih_k_offset(ih) + | ||
| 944 | ((old_len - tb->sbytes[i]) << (is_indirect_le_ih(ih) ? tb->tb_sb->s_blocksize_bits - UNFM_P_SHIFT : 0))); | ||
| 945 | |||
| 946 | put_ih_item_len(ih, tb->sbytes[i]); | ||
| 947 | |||
| 948 | /* Insert part of the item into S_new[i] before 0-th item */ | ||
| 949 | buffer_info_init_bh(tb, &bi, tb->S_new[i]); | ||
| 950 | |||
| 951 | if ((old_len - tb->sbytes[i]) > tb->zeroes_num) { | ||
| 952 | r_zeroes_number = 0; | ||
| 953 | r_body = body + (old_len - tb->sbytes[i]) - tb->zeroes_num; | ||
| 954 | } else { | ||
| 955 | r_body = body; | ||
| 956 | r_zeroes_number = tb->zeroes_num - (old_len - tb->sbytes[i]); | ||
| 957 | tb->zeroes_num -= r_zeroes_number; | ||
| 958 | } | ||
| 959 | 928 | ||
| 960 | leaf_insert_into_buf(&bi, 0, ih, r_body, r_zeroes_number); | 929 | /* new item or it part don't falls into S_new[i] */ |
| 930 | if (n - tb->snum[i] >= tb->item_pos) { | ||
| 931 | leaf_move_items(LEAF_FROM_S_TO_SNEW, tb, | ||
| 932 | tb->snum[i], tb->sbytes[i], tb->S_new[i]); | ||
| 933 | return; | ||
| 934 | } | ||
| 961 | 935 | ||
| 962 | /* Calculate key component and item length to insert into S[i] */ | 936 | /* new item or it's part falls to first new node S_new[i] */ |
| 963 | set_le_ih_k_offset(ih, old_key_comp); | ||
| 964 | put_ih_item_len(ih, old_len - tb->sbytes[i]); | ||
| 965 | tb->insert_size[0] -= tb->sbytes[i]; | ||
| 966 | } else { /* whole new item falls into S_new[i] */ | ||
| 967 | 937 | ||
| 968 | /* Shift snum[0] - 1 items to S_new[i] (sbytes[i] of split item) */ | 938 | /* part of new item falls into S_new[i] */ |
| 969 | leaf_move_items(LEAF_FROM_S_TO_SNEW, tb, | 939 | if (tb->item_pos == n - tb->snum[i] + 1 && tb->sbytes[i] != -1) { |
| 970 | tb->snum[i] - 1, tb->sbytes[i], tb->S_new[i]); | 940 | int old_key_comp, old_len, r_zeroes_number; |
| 941 | const char *r_body; | ||
| 942 | int version; | ||
| 971 | 943 | ||
| 972 | /* Insert new item into S_new[i] */ | 944 | /* Move snum[i]-1 items from S[0] to S_new[i] */ |
| 973 | buffer_info_init_bh(tb, &bi, tb->S_new[i]); | 945 | leaf_move_items(LEAF_FROM_S_TO_SNEW, tb, tb->snum[i] - 1, -1, |
| 974 | leaf_insert_into_buf(&bi, tb->item_pos - n + tb->snum[i] - 1, | 946 | tb->S_new[i]); |
| 975 | ih, body, tb->zeroes_num); | ||
| 976 | 947 | ||
| 977 | tb->zeroes_num = tb->insert_size[0] = 0; | 948 | /* Remember key component and item length */ |
| 978 | } | 949 | version = ih_version(ih); |
| 979 | } | 950 | old_key_comp = le_ih_k_offset(ih); |
| 951 | old_len = ih_item_len(ih); | ||
| 952 | |||
| 953 | /* | ||
| 954 | * Calculate key component and item length to insert | ||
| 955 | * into S_new[i] | ||
| 956 | */ | ||
| 957 | shift = 0; | ||
| 958 | if (is_indirect_le_ih(ih)) | ||
| 959 | shift = tb->tb_sb->s_blocksize_bits - UNFM_P_SHIFT; | ||
| 960 | set_le_ih_k_offset(ih, | ||
| 961 | le_ih_k_offset(ih) + | ||
| 962 | ((old_len - tb->sbytes[i]) << shift)); | ||
| 980 | 963 | ||
| 981 | else { /* new item or it part don't falls into S_new[i] */ | 964 | put_ih_item_len(ih, tb->sbytes[i]); |
| 982 | 965 | ||
| 983 | leaf_move_items(LEAF_FROM_S_TO_SNEW, tb, | 966 | /* Insert part of the item into S_new[i] before 0-th item */ |
| 984 | tb->snum[i], tb->sbytes[i], tb->S_new[i]); | 967 | buffer_info_init_bh(tb, &bi, tb->S_new[i]); |
| 985 | } | 968 | |
| 969 | if ((old_len - tb->sbytes[i]) > tb->zeroes_num) { | ||
| 970 | r_zeroes_number = 0; | ||
| 971 | r_body = body + (old_len - tb->sbytes[i]) - | ||
| 972 | tb->zeroes_num; | ||
| 973 | } else { | ||
| 974 | r_body = body; | ||
| 975 | r_zeroes_number = tb->zeroes_num - (old_len - | ||
| 976 | tb->sbytes[i]); | ||
| 977 | tb->zeroes_num -= r_zeroes_number; | ||
| 978 | } | ||
| 979 | |||
| 980 | leaf_insert_into_buf(&bi, 0, ih, r_body, r_zeroes_number); | ||
| 981 | |||
| 982 | /* | ||
| 983 | * Calculate key component and item length to | ||
| 984 | * insert into S[i] | ||
| 985 | */ | ||
| 986 | set_le_ih_k_offset(ih, old_key_comp); | ||
| 987 | put_ih_item_len(ih, old_len - tb->sbytes[i]); | ||
| 988 | tb->insert_size[0] -= tb->sbytes[i]; | ||
| 989 | } else { | ||
| 990 | /* whole new item falls into S_new[i] */ | ||
| 991 | |||
| 992 | /* | ||
| 993 | * Shift snum[0] - 1 items to S_new[i] | ||
| 994 | * (sbytes[i] of split item) | ||
| 995 | */ | ||
| 996 | leaf_move_items(LEAF_FROM_S_TO_SNEW, tb, | ||
| 997 | tb->snum[i] - 1, tb->sbytes[i], tb->S_new[i]); | ||
| 998 | |||
| 999 | /* Insert new item into S_new[i] */ | ||
| 1000 | buffer_info_init_bh(tb, &bi, tb->S_new[i]); | ||
| 1001 | leaf_insert_into_buf(&bi, tb->item_pos - n + tb->snum[i] - 1, | ||
| 1002 | ih, body, tb->zeroes_num); | ||
| 1003 | |||
| 1004 | tb->zeroes_num = tb->insert_size[0] = 0; | ||
| 1005 | } | ||
| 986 | } | 1006 | } |
| 987 | 1007 | ||
| 988 | static void balance_leaf_new_nodes_paste(struct tree_balance *tb, | 1008 | /* we append to directory item */ |
| 1009 | static void balance_leaf_new_nodes_paste_dirent(struct tree_balance *tb, | ||
| 989 | struct item_head *ih, | 1010 | struct item_head *ih, |
| 990 | const char *body, | 1011 | const char *body, |
| 991 | struct item_head *insert_key, | 1012 | struct item_head *insert_key, |
| @@ -993,153 +1014,206 @@ static void balance_leaf_new_nodes_paste(struct tree_balance *tb, | |||
| 993 | int i) | 1014 | int i) |
| 994 | { | 1015 | { |
| 995 | struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path); | 1016 | struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path); |
| 996 | int n = B_NR_ITEMS(tbS0); | 1017 | struct item_head *aux_ih = item_head(tbS0, tb->item_pos); |
| 1018 | int entry_count = ih_entry_count(aux_ih); | ||
| 997 | struct buffer_info bi; | 1019 | struct buffer_info bi; |
| 998 | if (n - tb->snum[i] <= tb->item_pos) { /* pasted item or part if it falls to S_new[i] */ | ||
| 999 | if (tb->item_pos == n - tb->snum[i] && tb->sbytes[i] != -1) { /* we must shift part of the appended item */ | ||
| 1000 | struct item_head *aux_ih; | ||
| 1001 | |||
| 1002 | RFALSE(ih, "PAP-12210: ih must be 0"); | ||
| 1003 | |||
| 1004 | aux_ih = item_head(tbS0, tb->item_pos); | ||
| 1005 | if (is_direntry_le_ih(aux_ih)) { | ||
| 1006 | /* we append to directory item */ | ||
| 1007 | |||
| 1008 | int entry_count; | ||
| 1009 | |||
| 1010 | entry_count = ih_entry_count(aux_ih); | ||
| 1011 | |||
| 1012 | if (entry_count - tb->sbytes[i] < tb->pos_in_item && tb->pos_in_item <= entry_count) { | ||
| 1013 | /* new directory entry falls into S_new[i] */ | ||
| 1014 | |||
| 1015 | RFALSE(!tb->insert_size[0], "PAP-12215: insert_size is already 0"); | ||
| 1016 | RFALSE(tb->sbytes[i] - 1 >= entry_count, | ||
| 1017 | "PAP-12220: there are no so much entries (%d), only %d", | ||
| 1018 | tb->sbytes[i] - 1, entry_count); | ||
| 1019 | |||
| 1020 | /* Shift snum[i]-1 items in whole. Shift sbytes[i] directory entries from directory item number snum[i] */ | ||
| 1021 | leaf_move_items(LEAF_FROM_S_TO_SNEW, tb, tb->snum[i], tb->sbytes[i] - 1, tb->S_new[i]); | ||
| 1022 | /* Paste given directory entry to directory item */ | ||
| 1023 | buffer_info_init_bh(tb, &bi, tb->S_new[i]); | ||
| 1024 | leaf_paste_in_buffer(&bi, 0, tb->pos_in_item - entry_count + tb->sbytes[i] - 1, | ||
| 1025 | tb->insert_size[0], body, tb->zeroes_num); | ||
| 1026 | /* paste new directory entry */ | ||
| 1027 | leaf_paste_entries(&bi, 0, tb->pos_in_item - entry_count + tb->sbytes[i] - 1, 1, | ||
| 1028 | (struct reiserfs_de_head *) body, | ||
| 1029 | body + DEH_SIZE, tb->insert_size[0]); | ||
| 1030 | tb->insert_size[0] = 0; | ||
| 1031 | tb->pos_in_item++; | ||
| 1032 | } else { /* new directory entry doesn't fall into S_new[i] */ | ||
| 1033 | leaf_move_items(LEAF_FROM_S_TO_SNEW, tb, tb->snum[i], tb->sbytes[i], tb->S_new[i]); | ||
| 1034 | } | ||
| 1035 | } else { /* regular object */ | ||
| 1036 | |||
| 1037 | int n_shift, n_rem, r_zeroes_number; | ||
| 1038 | const char *r_body; | ||
| 1039 | |||
| 1040 | RFALSE(tb->pos_in_item != ih_item_len(item_head(tbS0, tb->item_pos)) || tb->insert_size[0] <= 0, | ||
| 1041 | "PAP-12225: item too short or insert_size <= 0"); | ||
| 1042 | |||
| 1043 | /* Calculate number of bytes which must be shifted from appended item */ | ||
| 1044 | n_shift = tb->sbytes[i] - tb->insert_size[0]; | ||
| 1045 | if (n_shift < 0) | ||
| 1046 | n_shift = 0; | ||
| 1047 | leaf_move_items(LEAF_FROM_S_TO_SNEW, tb, tb->snum[i], n_shift, tb->S_new[i]); | ||
| 1048 | |||
| 1049 | /* Calculate number of bytes which must remain in body after append to S_new[i] */ | ||
| 1050 | n_rem = tb->insert_size[0] - tb->sbytes[i]; | ||
| 1051 | if (n_rem < 0) | ||
| 1052 | n_rem = 0; | ||
| 1053 | /* Append part of body into S_new[0] */ | ||
| 1054 | buffer_info_init_bh(tb, &bi, tb->S_new[i]); | ||
| 1055 | if (n_rem > tb->zeroes_num) { | ||
| 1056 | r_zeroes_number = 0; | ||
| 1057 | r_body = body + n_rem - tb->zeroes_num; | ||
| 1058 | } else { | ||
| 1059 | r_body = body; | ||
| 1060 | r_zeroes_number = tb->zeroes_num - n_rem; | ||
| 1061 | tb->zeroes_num -= r_zeroes_number; | ||
| 1062 | } | ||
| 1063 | 1020 | ||
| 1064 | leaf_paste_in_buffer(&bi, 0, n_shift, | 1021 | if (entry_count - tb->sbytes[i] < tb->pos_in_item && |
| 1065 | tb->insert_size[0] - n_rem, | 1022 | tb->pos_in_item <= entry_count) { |
| 1066 | r_body, r_zeroes_number); | 1023 | /* new directory entry falls into S_new[i] */ |
| 1067 | { | ||
| 1068 | struct item_head *tmp; | ||
| 1069 | |||
| 1070 | tmp = item_head(tb->S_new[i], 0); | ||
| 1071 | if (is_indirect_le_ih | ||
| 1072 | (tmp)) { | ||
| 1073 | set_ih_free_space(tmp, 0); | ||
| 1074 | set_le_ih_k_offset(tmp, le_ih_k_offset(tmp) + (n_rem << (tb->tb_sb->s_blocksize_bits - UNFM_P_SHIFT))); | ||
| 1075 | } else { | ||
| 1076 | set_le_ih_k_offset(tmp, le_ih_k_offset(tmp) + n_rem); | ||
| 1077 | } | ||
| 1078 | } | ||
| 1079 | 1024 | ||
| 1080 | tb->insert_size[0] = n_rem; | 1025 | RFALSE(!tb->insert_size[0], |
| 1081 | if (!n_rem) | 1026 | "PAP-12215: insert_size is already 0"); |
| 1082 | tb->pos_in_item++; | 1027 | RFALSE(tb->sbytes[i] - 1 >= entry_count, |
| 1083 | } | 1028 | "PAP-12220: there are no so much entries (%d), only %d", |
| 1084 | } else | 1029 | tb->sbytes[i] - 1, entry_count); |
| 1085 | /* item falls wholly into S_new[i] */ | 1030 | |
| 1086 | { | 1031 | /* |
| 1087 | int leaf_mi; | 1032 | * Shift snum[i]-1 items in whole. |
| 1088 | struct item_head *pasted; | 1033 | * Shift sbytes[i] directory entries |
| 1034 | * from directory item number snum[i] | ||
| 1035 | */ | ||
| 1036 | leaf_move_items(LEAF_FROM_S_TO_SNEW, tb, tb->snum[i], | ||
| 1037 | tb->sbytes[i] - 1, tb->S_new[i]); | ||
| 1038 | |||
| 1039 | /* | ||
| 1040 | * Paste given directory entry to | ||
| 1041 | * directory item | ||
| 1042 | */ | ||
| 1043 | buffer_info_init_bh(tb, &bi, tb->S_new[i]); | ||
| 1044 | leaf_paste_in_buffer(&bi, 0, tb->pos_in_item - entry_count + | ||
| 1045 | tb->sbytes[i] - 1, tb->insert_size[0], | ||
| 1046 | body, tb->zeroes_num); | ||
| 1047 | |||
| 1048 | /* paste new directory entry */ | ||
| 1049 | leaf_paste_entries(&bi, 0, tb->pos_in_item - entry_count + | ||
| 1050 | tb->sbytes[i] - 1, 1, | ||
| 1051 | (struct reiserfs_de_head *) body, | ||
| 1052 | body + DEH_SIZE, tb->insert_size[0]); | ||
| 1053 | |||
| 1054 | tb->insert_size[0] = 0; | ||
| 1055 | tb->pos_in_item++; | ||
| 1056 | } else { | ||
| 1057 | /* new directory entry doesn't fall into S_new[i] */ | ||
| 1058 | leaf_move_items(LEAF_FROM_S_TO_SNEW, tb, tb->snum[i], | ||
| 1059 | tb->sbytes[i], tb->S_new[i]); | ||
| 1060 | } | ||
| 1061 | |||
| 1062 | } | ||
| 1063 | |||
| 1064 | static void balance_leaf_new_nodes_paste_shift(struct tree_balance *tb, | ||
| 1065 | struct item_head *ih, | ||
| 1066 | const char *body, | ||
| 1067 | struct item_head *insert_key, | ||
| 1068 | struct buffer_head **insert_ptr, | ||
| 1069 | int i) | ||
| 1070 | { | ||
| 1071 | struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path); | ||
| 1072 | struct item_head *aux_ih = item_head(tbS0, tb->item_pos); | ||
| 1073 | int n_shift, n_rem, r_zeroes_number, shift; | ||
| 1074 | const char *r_body; | ||
| 1075 | struct item_head *tmp; | ||
| 1076 | struct buffer_info bi; | ||
| 1077 | |||
| 1078 | RFALSE(ih, "PAP-12210: ih must be 0"); | ||
| 1079 | |||
| 1080 | if (is_direntry_le_ih(aux_ih)) { | ||
| 1081 | balance_leaf_new_nodes_paste_dirent(tb, ih, body, insert_key, | ||
| 1082 | insert_ptr, i); | ||
| 1083 | return; | ||
| 1084 | } | ||
| 1085 | |||
| 1086 | /* regular object */ | ||
| 1087 | |||
| 1088 | |||
| 1089 | RFALSE(tb->pos_in_item != ih_item_len(item_head(tbS0, tb->item_pos)) || | ||
| 1090 | tb->insert_size[0] <= 0, | ||
| 1091 | "PAP-12225: item too short or insert_size <= 0"); | ||
| 1092 | |||
| 1093 | /* | ||
| 1094 | * Calculate number of bytes which must be shifted from appended item | ||
| 1095 | */ | ||
| 1096 | n_shift = tb->sbytes[i] - tb->insert_size[0]; | ||
| 1097 | if (n_shift < 0) | ||
| 1098 | n_shift = 0; | ||
| 1099 | leaf_move_items(LEAF_FROM_S_TO_SNEW, tb, tb->snum[i], n_shift, | ||
| 1100 | tb->S_new[i]); | ||
| 1101 | |||
| 1102 | /* | ||
| 1103 | * Calculate number of bytes which must remain in body after | ||
| 1104 | * append to S_new[i] | ||
| 1105 | */ | ||
| 1106 | n_rem = tb->insert_size[0] - tb->sbytes[i]; | ||
| 1107 | if (n_rem < 0) | ||
| 1108 | n_rem = 0; | ||
| 1109 | |||
| 1110 | /* Append part of body into S_new[0] */ | ||
| 1111 | buffer_info_init_bh(tb, &bi, tb->S_new[i]); | ||
| 1112 | if (n_rem > tb->zeroes_num) { | ||
| 1113 | r_zeroes_number = 0; | ||
| 1114 | r_body = body + n_rem - tb->zeroes_num; | ||
| 1115 | } else { | ||
| 1116 | r_body = body; | ||
| 1117 | r_zeroes_number = tb->zeroes_num - n_rem; | ||
| 1118 | tb->zeroes_num -= r_zeroes_number; | ||
| 1119 | } | ||
| 1120 | |||
| 1121 | leaf_paste_in_buffer(&bi, 0, n_shift, tb->insert_size[0] - n_rem, | ||
| 1122 | r_body, r_zeroes_number); | ||
| 1123 | |||
| 1124 | tmp = item_head(tb->S_new[i], 0); | ||
| 1125 | shift = 0; | ||
| 1126 | if (is_indirect_le_ih(tmp)) { | ||
| 1127 | set_ih_free_space(tmp, 0); | ||
| 1128 | shift = tb->tb_sb->s_blocksize_bits - UNFM_P_SHIFT; | ||
| 1129 | } | ||
| 1130 | add_le_ih_k_offset(tmp, n_rem << shift); | ||
| 1131 | |||
| 1132 | tb->insert_size[0] = n_rem; | ||
| 1133 | if (!n_rem) | ||
| 1134 | tb->pos_in_item++; | ||
| 1135 | } | ||
| 1136 | |||
| 1137 | static void balance_leaf_new_nodes_paste_whole(struct tree_balance *tb, | ||
| 1138 | struct item_head *ih, | ||
| 1139 | const char *body, | ||
| 1140 | struct item_head *insert_key, | ||
| 1141 | struct buffer_head **insert_ptr, | ||
| 1142 | int i) | ||
| 1143 | |||
| 1144 | { | ||
| 1145 | struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path); | ||
| 1146 | int n = B_NR_ITEMS(tbS0); | ||
| 1147 | int leaf_mi; | ||
| 1148 | struct item_head *pasted; | ||
| 1149 | struct buffer_info bi; | ||
| 1089 | 1150 | ||
| 1090 | #ifdef CONFIG_REISERFS_CHECK | 1151 | #ifdef CONFIG_REISERFS_CHECK |
| 1091 | struct item_head *ih_check = item_head(tbS0, tb->item_pos); | 1152 | struct item_head *ih_check = item_head(tbS0, tb->item_pos); |
| 1092 | |||
| 1093 | if (!is_direntry_le_ih(ih_check) | ||
| 1094 | && (tb->pos_in_item != ih_item_len(ih_check) | ||
| 1095 | || tb->insert_size[0] <= 0)) | ||
| 1096 | reiserfs_panic(tb->tb_sb, | ||
| 1097 | "PAP-12235", | ||
| 1098 | "pos_in_item " | ||
| 1099 | "must be equal " | ||
| 1100 | "to ih_item_len"); | ||
| 1101 | #endif /* CONFIG_REISERFS_CHECK */ | ||
| 1102 | 1153 | ||
| 1103 | leaf_mi = leaf_move_items(LEAF_FROM_S_TO_SNEW, | 1154 | if (!is_direntry_le_ih(ih_check) && |
| 1104 | tb, tb->snum[i], | 1155 | (tb->pos_in_item != ih_item_len(ih_check) || |
| 1105 | tb->sbytes[i], | 1156 | tb->insert_size[0] <= 0)) |
| 1106 | tb->S_new[i]); | 1157 | reiserfs_panic(tb->tb_sb, |
| 1107 | 1158 | "PAP-12235", | |
| 1108 | RFALSE(leaf_mi, | 1159 | "pos_in_item must be equal to ih_item_len"); |
| 1109 | "PAP-12240: unexpected value returned by leaf_move_items (%d)", | 1160 | #endif |
| 1110 | leaf_mi); | ||
| 1111 | |||
| 1112 | /* paste into item */ | ||
| 1113 | buffer_info_init_bh(tb, &bi, tb->S_new[i]); | ||
| 1114 | leaf_paste_in_buffer(&bi, | ||
| 1115 | tb->item_pos - n + tb->snum[i], | ||
| 1116 | tb->pos_in_item, | ||
| 1117 | tb->insert_size[0], | ||
| 1118 | body, tb->zeroes_num); | ||
| 1119 | |||
| 1120 | pasted = item_head(tb->S_new[i], tb->item_pos - n + tb->snum[i]); | ||
| 1121 | if (is_direntry_le_ih(pasted)) { | ||
| 1122 | leaf_paste_entries(&bi, | ||
| 1123 | tb->item_pos - n + tb->snum[i], | ||
| 1124 | tb->pos_in_item, 1, | ||
| 1125 | (struct reiserfs_de_head *)body, | ||
| 1126 | body + DEH_SIZE, | ||
| 1127 | tb->insert_size[0]); | ||
| 1128 | } | ||
| 1129 | 1161 | ||
| 1130 | /* if we paste to indirect item update ih_free_space */ | 1162 | leaf_mi = leaf_move_items(LEAF_FROM_S_TO_SNEW, tb, tb->snum[i], |
| 1131 | if (is_indirect_le_ih(pasted)) | 1163 | tb->sbytes[i], tb->S_new[i]); |
| 1132 | set_ih_free_space(pasted, 0); | ||
| 1133 | tb->zeroes_num = tb->insert_size[0] = 0; | ||
| 1134 | } | ||
| 1135 | } | ||
| 1136 | 1164 | ||
| 1137 | else { /* pasted item doesn't fall into S_new[i] */ | 1165 | RFALSE(leaf_mi, |
| 1166 | "PAP-12240: unexpected value returned by leaf_move_items (%d)", | ||
| 1167 | leaf_mi); | ||
| 1138 | 1168 | ||
| 1139 | leaf_move_items(LEAF_FROM_S_TO_SNEW, tb, | 1169 | /* paste into item */ |
| 1140 | tb->snum[i], tb->sbytes[i], tb->S_new[i]); | 1170 | buffer_info_init_bh(tb, &bi, tb->S_new[i]); |
| 1141 | } | 1171 | leaf_paste_in_buffer(&bi, tb->item_pos - n + tb->snum[i], |
| 1172 | tb->pos_in_item, tb->insert_size[0], | ||
| 1173 | body, tb->zeroes_num); | ||
| 1174 | |||
| 1175 | pasted = item_head(tb->S_new[i], tb->item_pos - n + | ||
| 1176 | tb->snum[i]); | ||
| 1177 | if (is_direntry_le_ih(pasted)) | ||
| 1178 | leaf_paste_entries(&bi, tb->item_pos - n + tb->snum[i], | ||
| 1179 | tb->pos_in_item, 1, | ||
| 1180 | (struct reiserfs_de_head *)body, | ||
| 1181 | body + DEH_SIZE, tb->insert_size[0]); | ||
| 1182 | |||
| 1183 | /* if we paste to indirect item update ih_free_space */ | ||
| 1184 | if (is_indirect_le_ih(pasted)) | ||
| 1185 | set_ih_free_space(pasted, 0); | ||
| 1186 | |||
| 1187 | tb->zeroes_num = tb->insert_size[0] = 0; | ||
| 1188 | |||
| 1189 | } | ||
| 1190 | static void balance_leaf_new_nodes_paste(struct tree_balance *tb, | ||
| 1191 | struct item_head *ih, | ||
| 1192 | const char *body, | ||
| 1193 | struct item_head *insert_key, | ||
| 1194 | struct buffer_head **insert_ptr, | ||
| 1195 | int i) | ||
| 1196 | { | ||
| 1197 | struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path); | ||
| 1198 | int n = B_NR_ITEMS(tbS0); | ||
| 1199 | |||
| 1200 | /* pasted item doesn't fall into S_new[i] */ | ||
| 1201 | if (n - tb->snum[i] > tb->item_pos) { | ||
| 1202 | leaf_move_items(LEAF_FROM_S_TO_SNEW, tb, | ||
| 1203 | tb->snum[i], tb->sbytes[i], tb->S_new[i]); | ||
| 1204 | return; | ||
| 1205 | } | ||
| 1206 | |||
| 1207 | /* pasted item or part if it falls to S_new[i] */ | ||
| 1142 | 1208 | ||
| 1209 | if (tb->item_pos == n - tb->snum[i] && tb->sbytes[i] != -1) | ||
| 1210 | /* we must shift part of the appended item */ | ||
| 1211 | balance_leaf_new_nodes_paste_shift(tb, ih, body, insert_key, | ||
| 1212 | insert_ptr, i); | ||
| 1213 | else | ||
| 1214 | /* item falls wholly into S_new[i] */ | ||
| 1215 | balance_leaf_new_nodes_paste_whole(tb, ih, body, insert_key, | ||
| 1216 | insert_ptr, i); | ||
| 1143 | } | 1217 | } |
| 1144 | 1218 | ||
| 1145 | /* Fill new nodes that appear in place of S[0] */ | 1219 | /* Fill new nodes that appear in place of S[0] */ |
| @@ -1152,6 +1226,7 @@ static void balance_leaf_new_nodes(struct tree_balance *tb, | |||
| 1152 | { | 1226 | { |
| 1153 | int i; | 1227 | int i; |
| 1154 | for (i = tb->blknum[0] - 2; i >= 0; i--) { | 1228 | for (i = tb->blknum[0] - 2; i >= 0; i--) { |
| 1229 | BUG_ON(flag != M_INSERT && flag != M_PASTE); | ||
| 1155 | 1230 | ||
| 1156 | RFALSE(!tb->snum[i], | 1231 | RFALSE(!tb->snum[i], |
| 1157 | "PAP-12200: snum[%d] == %d. Must be > 0", i, | 1232 | "PAP-12200: snum[%d] == %d. Must be > 0", i, |
| @@ -1164,21 +1239,12 @@ static void balance_leaf_new_nodes(struct tree_balance *tb, | |||
| 1164 | /* initialized block type and tree level */ | 1239 | /* initialized block type and tree level */ |
| 1165 | set_blkh_level(B_BLK_HEAD(tb->S_new[i]), DISK_LEAF_NODE_LEVEL); | 1240 | set_blkh_level(B_BLK_HEAD(tb->S_new[i]), DISK_LEAF_NODE_LEVEL); |
| 1166 | 1241 | ||
| 1167 | switch (flag) { | 1242 | if (flag == M_INSERT) |
| 1168 | case M_INSERT: /* insert item */ | ||
| 1169 | balance_leaf_new_nodes_insert(tb, ih, body, insert_key, | 1243 | balance_leaf_new_nodes_insert(tb, ih, body, insert_key, |
| 1170 | insert_ptr, i); | 1244 | insert_ptr, i); |
| 1171 | break; | 1245 | else /* M_PASTE */ |
| 1172 | |||
| 1173 | case M_PASTE: /* append item */ | ||
| 1174 | balance_leaf_new_nodes_paste(tb, ih, body, insert_key, | 1246 | balance_leaf_new_nodes_paste(tb, ih, body, insert_key, |
| 1175 | insert_ptr, i); | 1247 | insert_ptr, i); |
| 1176 | break; | ||
| 1177 | default: /* cases d and t */ | ||
| 1178 | reiserfs_panic(tb->tb_sb, "PAP-12245", | ||
| 1179 | "blknum > 2: unexpected mode: %s(%d)", | ||
| 1180 | (flag == M_DELETE) ? "DELETE" : ((flag == M_CUT) ? "CUT" : "UNKNOWN"), flag); | ||
| 1181 | } | ||
| 1182 | 1248 | ||
| 1183 | memcpy(insert_key + i, leaf_key(tb->S_new[i], 0), KEY_SIZE); | 1249 | memcpy(insert_key + i, leaf_key(tb->S_new[i], 0), KEY_SIZE); |
| 1184 | insert_ptr[i] = tb->S_new[i]; | 1250 | insert_ptr[i] = tb->S_new[i]; |
