18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README 38c2ecf20Sopenharmony_ci */ 48c2ecf20Sopenharmony_ci 58c2ecf20Sopenharmony_ci#include <linux/uaccess.h> 68c2ecf20Sopenharmony_ci#include <linux/string.h> 78c2ecf20Sopenharmony_ci#include <linux/time.h> 88c2ecf20Sopenharmony_ci#include "reiserfs.h" 98c2ecf20Sopenharmony_ci#include <linux/buffer_head.h> 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci/* this is one and only function that is used outside (do_balance.c) */ 128c2ecf20Sopenharmony_ciint balance_internal(struct tree_balance *, 138c2ecf20Sopenharmony_ci int, int, struct item_head *, struct buffer_head **); 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci/* 168c2ecf20Sopenharmony_ci * modes of internal_shift_left, internal_shift_right and 178c2ecf20Sopenharmony_ci * internal_insert_childs 188c2ecf20Sopenharmony_ci */ 198c2ecf20Sopenharmony_ci#define INTERNAL_SHIFT_FROM_S_TO_L 0 208c2ecf20Sopenharmony_ci#define INTERNAL_SHIFT_FROM_R_TO_S 1 218c2ecf20Sopenharmony_ci#define INTERNAL_SHIFT_FROM_L_TO_S 2 228c2ecf20Sopenharmony_ci#define INTERNAL_SHIFT_FROM_S_TO_R 3 238c2ecf20Sopenharmony_ci#define INTERNAL_INSERT_TO_S 4 248c2ecf20Sopenharmony_ci#define INTERNAL_INSERT_TO_L 5 258c2ecf20Sopenharmony_ci#define INTERNAL_INSERT_TO_R 6 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_cistatic void internal_define_dest_src_infos(int shift_mode, 288c2ecf20Sopenharmony_ci struct tree_balance *tb, 298c2ecf20Sopenharmony_ci int h, 308c2ecf20Sopenharmony_ci struct buffer_info *dest_bi, 318c2ecf20Sopenharmony_ci struct buffer_info *src_bi, 328c2ecf20Sopenharmony_ci int *d_key, struct buffer_head **cf) 338c2ecf20Sopenharmony_ci{ 348c2ecf20Sopenharmony_ci memset(dest_bi, 0, sizeof(struct buffer_info)); 358c2ecf20Sopenharmony_ci memset(src_bi, 0, sizeof(struct buffer_info)); 368c2ecf20Sopenharmony_ci /* define dest, src, dest parent, dest position */ 378c2ecf20Sopenharmony_ci switch (shift_mode) { 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci /* used in internal_shift_left */ 408c2ecf20Sopenharmony_ci case INTERNAL_SHIFT_FROM_S_TO_L: 418c2ecf20Sopenharmony_ci src_bi->tb = tb; 428c2ecf20Sopenharmony_ci src_bi->bi_bh = PATH_H_PBUFFER(tb->tb_path, h); 438c2ecf20Sopenharmony_ci src_bi->bi_parent = PATH_H_PPARENT(tb->tb_path, h); 448c2ecf20Sopenharmony_ci src_bi->bi_position = PATH_H_POSITION(tb->tb_path, h + 1); 458c2ecf20Sopenharmony_ci dest_bi->tb = tb; 468c2ecf20Sopenharmony_ci dest_bi->bi_bh = tb->L[h]; 478c2ecf20Sopenharmony_ci dest_bi->bi_parent = tb->FL[h]; 488c2ecf20Sopenharmony_ci dest_bi->bi_position = get_left_neighbor_position(tb, h); 498c2ecf20Sopenharmony_ci *d_key = tb->lkey[h]; 508c2ecf20Sopenharmony_ci *cf = tb->CFL[h]; 518c2ecf20Sopenharmony_ci break; 528c2ecf20Sopenharmony_ci case INTERNAL_SHIFT_FROM_L_TO_S: 538c2ecf20Sopenharmony_ci src_bi->tb = tb; 548c2ecf20Sopenharmony_ci src_bi->bi_bh = tb->L[h]; 558c2ecf20Sopenharmony_ci src_bi->bi_parent = tb->FL[h]; 568c2ecf20Sopenharmony_ci src_bi->bi_position = get_left_neighbor_position(tb, h); 578c2ecf20Sopenharmony_ci dest_bi->tb = tb; 588c2ecf20Sopenharmony_ci dest_bi->bi_bh = PATH_H_PBUFFER(tb->tb_path, h); 598c2ecf20Sopenharmony_ci dest_bi->bi_parent = PATH_H_PPARENT(tb->tb_path, h); 608c2ecf20Sopenharmony_ci /* dest position is analog of dest->b_item_order */ 618c2ecf20Sopenharmony_ci dest_bi->bi_position = PATH_H_POSITION(tb->tb_path, h + 1); 628c2ecf20Sopenharmony_ci *d_key = tb->lkey[h]; 638c2ecf20Sopenharmony_ci *cf = tb->CFL[h]; 648c2ecf20Sopenharmony_ci break; 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci /* used in internal_shift_left */ 678c2ecf20Sopenharmony_ci case INTERNAL_SHIFT_FROM_R_TO_S: 688c2ecf20Sopenharmony_ci src_bi->tb = tb; 698c2ecf20Sopenharmony_ci src_bi->bi_bh = tb->R[h]; 708c2ecf20Sopenharmony_ci src_bi->bi_parent = tb->FR[h]; 718c2ecf20Sopenharmony_ci src_bi->bi_position = get_right_neighbor_position(tb, h); 728c2ecf20Sopenharmony_ci dest_bi->tb = tb; 738c2ecf20Sopenharmony_ci dest_bi->bi_bh = PATH_H_PBUFFER(tb->tb_path, h); 748c2ecf20Sopenharmony_ci dest_bi->bi_parent = PATH_H_PPARENT(tb->tb_path, h); 758c2ecf20Sopenharmony_ci dest_bi->bi_position = PATH_H_POSITION(tb->tb_path, h + 1); 768c2ecf20Sopenharmony_ci *d_key = tb->rkey[h]; 778c2ecf20Sopenharmony_ci *cf = tb->CFR[h]; 788c2ecf20Sopenharmony_ci break; 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci case INTERNAL_SHIFT_FROM_S_TO_R: 818c2ecf20Sopenharmony_ci src_bi->tb = tb; 828c2ecf20Sopenharmony_ci src_bi->bi_bh = PATH_H_PBUFFER(tb->tb_path, h); 838c2ecf20Sopenharmony_ci src_bi->bi_parent = PATH_H_PPARENT(tb->tb_path, h); 848c2ecf20Sopenharmony_ci src_bi->bi_position = PATH_H_POSITION(tb->tb_path, h + 1); 858c2ecf20Sopenharmony_ci dest_bi->tb = tb; 868c2ecf20Sopenharmony_ci dest_bi->bi_bh = tb->R[h]; 878c2ecf20Sopenharmony_ci dest_bi->bi_parent = tb->FR[h]; 888c2ecf20Sopenharmony_ci dest_bi->bi_position = get_right_neighbor_position(tb, h); 898c2ecf20Sopenharmony_ci *d_key = tb->rkey[h]; 908c2ecf20Sopenharmony_ci *cf = tb->CFR[h]; 918c2ecf20Sopenharmony_ci break; 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci case INTERNAL_INSERT_TO_L: 948c2ecf20Sopenharmony_ci dest_bi->tb = tb; 958c2ecf20Sopenharmony_ci dest_bi->bi_bh = tb->L[h]; 968c2ecf20Sopenharmony_ci dest_bi->bi_parent = tb->FL[h]; 978c2ecf20Sopenharmony_ci dest_bi->bi_position = get_left_neighbor_position(tb, h); 988c2ecf20Sopenharmony_ci break; 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci case INTERNAL_INSERT_TO_S: 1018c2ecf20Sopenharmony_ci dest_bi->tb = tb; 1028c2ecf20Sopenharmony_ci dest_bi->bi_bh = PATH_H_PBUFFER(tb->tb_path, h); 1038c2ecf20Sopenharmony_ci dest_bi->bi_parent = PATH_H_PPARENT(tb->tb_path, h); 1048c2ecf20Sopenharmony_ci dest_bi->bi_position = PATH_H_POSITION(tb->tb_path, h + 1); 1058c2ecf20Sopenharmony_ci break; 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci case INTERNAL_INSERT_TO_R: 1088c2ecf20Sopenharmony_ci dest_bi->tb = tb; 1098c2ecf20Sopenharmony_ci dest_bi->bi_bh = tb->R[h]; 1108c2ecf20Sopenharmony_ci dest_bi->bi_parent = tb->FR[h]; 1118c2ecf20Sopenharmony_ci dest_bi->bi_position = get_right_neighbor_position(tb, h); 1128c2ecf20Sopenharmony_ci break; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci default: 1158c2ecf20Sopenharmony_ci reiserfs_panic(tb->tb_sb, "ibalance-1", 1168c2ecf20Sopenharmony_ci "shift type is unknown (%d)", 1178c2ecf20Sopenharmony_ci shift_mode); 1188c2ecf20Sopenharmony_ci } 1198c2ecf20Sopenharmony_ci} 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci/* 1228c2ecf20Sopenharmony_ci * Insert count node pointers into buffer cur before position to + 1. 1238c2ecf20Sopenharmony_ci * Insert count items into buffer cur before position to. 1248c2ecf20Sopenharmony_ci * Items and node pointers are specified by inserted and bh respectively. 1258c2ecf20Sopenharmony_ci */ 1268c2ecf20Sopenharmony_cistatic void internal_insert_childs(struct buffer_info *cur_bi, 1278c2ecf20Sopenharmony_ci int to, int count, 1288c2ecf20Sopenharmony_ci struct item_head *inserted, 1298c2ecf20Sopenharmony_ci struct buffer_head **bh) 1308c2ecf20Sopenharmony_ci{ 1318c2ecf20Sopenharmony_ci struct buffer_head *cur = cur_bi->bi_bh; 1328c2ecf20Sopenharmony_ci struct block_head *blkh; 1338c2ecf20Sopenharmony_ci int nr; 1348c2ecf20Sopenharmony_ci struct reiserfs_key *ih; 1358c2ecf20Sopenharmony_ci struct disk_child new_dc[2]; 1368c2ecf20Sopenharmony_ci struct disk_child *dc; 1378c2ecf20Sopenharmony_ci int i; 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci if (count <= 0) 1408c2ecf20Sopenharmony_ci return; 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci blkh = B_BLK_HEAD(cur); 1438c2ecf20Sopenharmony_ci nr = blkh_nr_item(blkh); 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci RFALSE(count > 2, "too many children (%d) are to be inserted", count); 1468c2ecf20Sopenharmony_ci RFALSE(B_FREE_SPACE(cur) < count * (KEY_SIZE + DC_SIZE), 1478c2ecf20Sopenharmony_ci "no enough free space (%d), needed %d bytes", 1488c2ecf20Sopenharmony_ci B_FREE_SPACE(cur), count * (KEY_SIZE + DC_SIZE)); 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci /* prepare space for count disk_child */ 1518c2ecf20Sopenharmony_ci dc = B_N_CHILD(cur, to + 1); 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci memmove(dc + count, dc, (nr + 1 - (to + 1)) * DC_SIZE); 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci /* copy to_be_insert disk children */ 1568c2ecf20Sopenharmony_ci for (i = 0; i < count; i++) { 1578c2ecf20Sopenharmony_ci put_dc_size(&new_dc[i], 1588c2ecf20Sopenharmony_ci MAX_CHILD_SIZE(bh[i]) - B_FREE_SPACE(bh[i])); 1598c2ecf20Sopenharmony_ci put_dc_block_number(&new_dc[i], bh[i]->b_blocknr); 1608c2ecf20Sopenharmony_ci } 1618c2ecf20Sopenharmony_ci memcpy(dc, new_dc, DC_SIZE * count); 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci /* prepare space for count items */ 1648c2ecf20Sopenharmony_ci ih = internal_key(cur, ((to == -1) ? 0 : to)); 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci memmove(ih + count, ih, 1678c2ecf20Sopenharmony_ci (nr - to) * KEY_SIZE + (nr + 1 + count) * DC_SIZE); 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci /* copy item headers (keys) */ 1708c2ecf20Sopenharmony_ci memcpy(ih, inserted, KEY_SIZE); 1718c2ecf20Sopenharmony_ci if (count > 1) 1728c2ecf20Sopenharmony_ci memcpy(ih + 1, inserted + 1, KEY_SIZE); 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci /* sizes, item number */ 1758c2ecf20Sopenharmony_ci set_blkh_nr_item(blkh, blkh_nr_item(blkh) + count); 1768c2ecf20Sopenharmony_ci set_blkh_free_space(blkh, 1778c2ecf20Sopenharmony_ci blkh_free_space(blkh) - count * (DC_SIZE + 1788c2ecf20Sopenharmony_ci KEY_SIZE)); 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci do_balance_mark_internal_dirty(cur_bi->tb, cur, 0); 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ci /*&&&&&&&&&&&&&&&&&&&&&&&& */ 1838c2ecf20Sopenharmony_ci check_internal(cur); 1848c2ecf20Sopenharmony_ci /*&&&&&&&&&&&&&&&&&&&&&&&& */ 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci if (cur_bi->bi_parent) { 1878c2ecf20Sopenharmony_ci struct disk_child *t_dc = 1888c2ecf20Sopenharmony_ci B_N_CHILD(cur_bi->bi_parent, cur_bi->bi_position); 1898c2ecf20Sopenharmony_ci put_dc_size(t_dc, 1908c2ecf20Sopenharmony_ci dc_size(t_dc) + (count * (DC_SIZE + KEY_SIZE))); 1918c2ecf20Sopenharmony_ci do_balance_mark_internal_dirty(cur_bi->tb, cur_bi->bi_parent, 1928c2ecf20Sopenharmony_ci 0); 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci /*&&&&&&&&&&&&&&&&&&&&&&&& */ 1958c2ecf20Sopenharmony_ci check_internal(cur_bi->bi_parent); 1968c2ecf20Sopenharmony_ci /*&&&&&&&&&&&&&&&&&&&&&&&& */ 1978c2ecf20Sopenharmony_ci } 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci} 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci/* 2028c2ecf20Sopenharmony_ci * Delete del_num items and node pointers from buffer cur starting from 2038c2ecf20Sopenharmony_ci * the first_i'th item and first_p'th pointers respectively. 2048c2ecf20Sopenharmony_ci */ 2058c2ecf20Sopenharmony_cistatic void internal_delete_pointers_items(struct buffer_info *cur_bi, 2068c2ecf20Sopenharmony_ci int first_p, 2078c2ecf20Sopenharmony_ci int first_i, int del_num) 2088c2ecf20Sopenharmony_ci{ 2098c2ecf20Sopenharmony_ci struct buffer_head *cur = cur_bi->bi_bh; 2108c2ecf20Sopenharmony_ci int nr; 2118c2ecf20Sopenharmony_ci struct block_head *blkh; 2128c2ecf20Sopenharmony_ci struct reiserfs_key *key; 2138c2ecf20Sopenharmony_ci struct disk_child *dc; 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci RFALSE(cur == NULL, "buffer is 0"); 2168c2ecf20Sopenharmony_ci RFALSE(del_num < 0, 2178c2ecf20Sopenharmony_ci "negative number of items (%d) can not be deleted", del_num); 2188c2ecf20Sopenharmony_ci RFALSE(first_p < 0 || first_p + del_num > B_NR_ITEMS(cur) + 1 2198c2ecf20Sopenharmony_ci || first_i < 0, 2208c2ecf20Sopenharmony_ci "first pointer order (%d) < 0 or " 2218c2ecf20Sopenharmony_ci "no so many pointers (%d), only (%d) or " 2228c2ecf20Sopenharmony_ci "first key order %d < 0", first_p, first_p + del_num, 2238c2ecf20Sopenharmony_ci B_NR_ITEMS(cur) + 1, first_i); 2248c2ecf20Sopenharmony_ci if (del_num == 0) 2258c2ecf20Sopenharmony_ci return; 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci blkh = B_BLK_HEAD(cur); 2288c2ecf20Sopenharmony_ci nr = blkh_nr_item(blkh); 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci if (first_p == 0 && del_num == nr + 1) { 2318c2ecf20Sopenharmony_ci RFALSE(first_i != 0, 2328c2ecf20Sopenharmony_ci "1st deleted key must have order 0, not %d", first_i); 2338c2ecf20Sopenharmony_ci make_empty_node(cur_bi); 2348c2ecf20Sopenharmony_ci return; 2358c2ecf20Sopenharmony_ci } 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci RFALSE(first_i + del_num > B_NR_ITEMS(cur), 2388c2ecf20Sopenharmony_ci "first_i = %d del_num = %d " 2398c2ecf20Sopenharmony_ci "no so many keys (%d) in the node (%b)(%z)", 2408c2ecf20Sopenharmony_ci first_i, del_num, first_i + del_num, cur, cur); 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci /* deleting */ 2438c2ecf20Sopenharmony_ci dc = B_N_CHILD(cur, first_p); 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci memmove(dc, dc + del_num, (nr + 1 - first_p - del_num) * DC_SIZE); 2468c2ecf20Sopenharmony_ci key = internal_key(cur, first_i); 2478c2ecf20Sopenharmony_ci memmove(key, key + del_num, 2488c2ecf20Sopenharmony_ci (nr - first_i - del_num) * KEY_SIZE + (nr + 1 - 2498c2ecf20Sopenharmony_ci del_num) * DC_SIZE); 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci /* sizes, item number */ 2528c2ecf20Sopenharmony_ci set_blkh_nr_item(blkh, blkh_nr_item(blkh) - del_num); 2538c2ecf20Sopenharmony_ci set_blkh_free_space(blkh, 2548c2ecf20Sopenharmony_ci blkh_free_space(blkh) + 2558c2ecf20Sopenharmony_ci (del_num * (KEY_SIZE + DC_SIZE))); 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci do_balance_mark_internal_dirty(cur_bi->tb, cur, 0); 2588c2ecf20Sopenharmony_ci /*&&&&&&&&&&&&&&&&&&&&&&& */ 2598c2ecf20Sopenharmony_ci check_internal(cur); 2608c2ecf20Sopenharmony_ci /*&&&&&&&&&&&&&&&&&&&&&&& */ 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ci if (cur_bi->bi_parent) { 2638c2ecf20Sopenharmony_ci struct disk_child *t_dc; 2648c2ecf20Sopenharmony_ci t_dc = B_N_CHILD(cur_bi->bi_parent, cur_bi->bi_position); 2658c2ecf20Sopenharmony_ci put_dc_size(t_dc, 2668c2ecf20Sopenharmony_ci dc_size(t_dc) - (del_num * (KEY_SIZE + DC_SIZE))); 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ci do_balance_mark_internal_dirty(cur_bi->tb, cur_bi->bi_parent, 2698c2ecf20Sopenharmony_ci 0); 2708c2ecf20Sopenharmony_ci /*&&&&&&&&&&&&&&&&&&&&&&&& */ 2718c2ecf20Sopenharmony_ci check_internal(cur_bi->bi_parent); 2728c2ecf20Sopenharmony_ci /*&&&&&&&&&&&&&&&&&&&&&&&& */ 2738c2ecf20Sopenharmony_ci } 2748c2ecf20Sopenharmony_ci} 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci/* delete n node pointers and items starting from given position */ 2778c2ecf20Sopenharmony_cistatic void internal_delete_childs(struct buffer_info *cur_bi, int from, int n) 2788c2ecf20Sopenharmony_ci{ 2798c2ecf20Sopenharmony_ci int i_from; 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci i_from = (from == 0) ? from : from - 1; 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci /* 2848c2ecf20Sopenharmony_ci * delete n pointers starting from `from' position in CUR; 2858c2ecf20Sopenharmony_ci * delete n keys starting from 'i_from' position in CUR; 2868c2ecf20Sopenharmony_ci */ 2878c2ecf20Sopenharmony_ci internal_delete_pointers_items(cur_bi, from, i_from, n); 2888c2ecf20Sopenharmony_ci} 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci/* 2918c2ecf20Sopenharmony_ci * copy cpy_num node pointers and cpy_num - 1 items from buffer src to buffer 2928c2ecf20Sopenharmony_ci * dest 2938c2ecf20Sopenharmony_ci * last_first == FIRST_TO_LAST means that we copy first items 2948c2ecf20Sopenharmony_ci * from src to tail of dest 2958c2ecf20Sopenharmony_ci * last_first == LAST_TO_FIRST means that we copy last items 2968c2ecf20Sopenharmony_ci * from src to head of dest 2978c2ecf20Sopenharmony_ci */ 2988c2ecf20Sopenharmony_cistatic void internal_copy_pointers_items(struct buffer_info *dest_bi, 2998c2ecf20Sopenharmony_ci struct buffer_head *src, 3008c2ecf20Sopenharmony_ci int last_first, int cpy_num) 3018c2ecf20Sopenharmony_ci{ 3028c2ecf20Sopenharmony_ci /* 3038c2ecf20Sopenharmony_ci * ATTENTION! Number of node pointers in DEST is equal to number 3048c2ecf20Sopenharmony_ci * of items in DEST as delimiting key have already inserted to 3058c2ecf20Sopenharmony_ci * buffer dest. 3068c2ecf20Sopenharmony_ci */ 3078c2ecf20Sopenharmony_ci struct buffer_head *dest = dest_bi->bi_bh; 3088c2ecf20Sopenharmony_ci int nr_dest, nr_src; 3098c2ecf20Sopenharmony_ci int dest_order, src_order; 3108c2ecf20Sopenharmony_ci struct block_head *blkh; 3118c2ecf20Sopenharmony_ci struct reiserfs_key *key; 3128c2ecf20Sopenharmony_ci struct disk_child *dc; 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci nr_src = B_NR_ITEMS(src); 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci RFALSE(dest == NULL || src == NULL, 3178c2ecf20Sopenharmony_ci "src (%p) or dest (%p) buffer is 0", src, dest); 3188c2ecf20Sopenharmony_ci RFALSE(last_first != FIRST_TO_LAST && last_first != LAST_TO_FIRST, 3198c2ecf20Sopenharmony_ci "invalid last_first parameter (%d)", last_first); 3208c2ecf20Sopenharmony_ci RFALSE(nr_src < cpy_num - 1, 3218c2ecf20Sopenharmony_ci "no so many items (%d) in src (%d)", cpy_num, nr_src); 3228c2ecf20Sopenharmony_ci RFALSE(cpy_num < 0, "cpy_num less than 0 (%d)", cpy_num); 3238c2ecf20Sopenharmony_ci RFALSE(cpy_num - 1 + B_NR_ITEMS(dest) > (int)MAX_NR_KEY(dest), 3248c2ecf20Sopenharmony_ci "cpy_num (%d) + item number in dest (%d) can not be > MAX_NR_KEY(%d)", 3258c2ecf20Sopenharmony_ci cpy_num, B_NR_ITEMS(dest), MAX_NR_KEY(dest)); 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci if (cpy_num == 0) 3288c2ecf20Sopenharmony_ci return; 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci /* coping */ 3318c2ecf20Sopenharmony_ci blkh = B_BLK_HEAD(dest); 3328c2ecf20Sopenharmony_ci nr_dest = blkh_nr_item(blkh); 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ci /*dest_order = (last_first == LAST_TO_FIRST) ? 0 : nr_dest; */ 3358c2ecf20Sopenharmony_ci /*src_order = (last_first == LAST_TO_FIRST) ? (nr_src - cpy_num + 1) : 0; */ 3368c2ecf20Sopenharmony_ci (last_first == LAST_TO_FIRST) ? (dest_order = 0, src_order = 3378c2ecf20Sopenharmony_ci nr_src - cpy_num + 1) : (dest_order = 3388c2ecf20Sopenharmony_ci nr_dest, 3398c2ecf20Sopenharmony_ci src_order = 3408c2ecf20Sopenharmony_ci 0); 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_ci /* prepare space for cpy_num pointers */ 3438c2ecf20Sopenharmony_ci dc = B_N_CHILD(dest, dest_order); 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci memmove(dc + cpy_num, dc, (nr_dest - dest_order) * DC_SIZE); 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci /* insert pointers */ 3488c2ecf20Sopenharmony_ci memcpy(dc, B_N_CHILD(src, src_order), DC_SIZE * cpy_num); 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci /* prepare space for cpy_num - 1 item headers */ 3518c2ecf20Sopenharmony_ci key = internal_key(dest, dest_order); 3528c2ecf20Sopenharmony_ci memmove(key + cpy_num - 1, key, 3538c2ecf20Sopenharmony_ci KEY_SIZE * (nr_dest - dest_order) + DC_SIZE * (nr_dest + 3548c2ecf20Sopenharmony_ci cpy_num)); 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci /* insert headers */ 3578c2ecf20Sopenharmony_ci memcpy(key, internal_key(src, src_order), KEY_SIZE * (cpy_num - 1)); 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_ci /* sizes, item number */ 3608c2ecf20Sopenharmony_ci set_blkh_nr_item(blkh, blkh_nr_item(blkh) + (cpy_num - 1)); 3618c2ecf20Sopenharmony_ci set_blkh_free_space(blkh, 3628c2ecf20Sopenharmony_ci blkh_free_space(blkh) - (KEY_SIZE * (cpy_num - 1) + 3638c2ecf20Sopenharmony_ci DC_SIZE * cpy_num)); 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_ci do_balance_mark_internal_dirty(dest_bi->tb, dest, 0); 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_ci /*&&&&&&&&&&&&&&&&&&&&&&&& */ 3688c2ecf20Sopenharmony_ci check_internal(dest); 3698c2ecf20Sopenharmony_ci /*&&&&&&&&&&&&&&&&&&&&&&&& */ 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_ci if (dest_bi->bi_parent) { 3728c2ecf20Sopenharmony_ci struct disk_child *t_dc; 3738c2ecf20Sopenharmony_ci t_dc = B_N_CHILD(dest_bi->bi_parent, dest_bi->bi_position); 3748c2ecf20Sopenharmony_ci put_dc_size(t_dc, 3758c2ecf20Sopenharmony_ci dc_size(t_dc) + (KEY_SIZE * (cpy_num - 1) + 3768c2ecf20Sopenharmony_ci DC_SIZE * cpy_num)); 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ci do_balance_mark_internal_dirty(dest_bi->tb, dest_bi->bi_parent, 3798c2ecf20Sopenharmony_ci 0); 3808c2ecf20Sopenharmony_ci /*&&&&&&&&&&&&&&&&&&&&&&&& */ 3818c2ecf20Sopenharmony_ci check_internal(dest_bi->bi_parent); 3828c2ecf20Sopenharmony_ci /*&&&&&&&&&&&&&&&&&&&&&&&& */ 3838c2ecf20Sopenharmony_ci } 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci} 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci/* 3888c2ecf20Sopenharmony_ci * Copy cpy_num node pointers and cpy_num - 1 items from buffer src to 3898c2ecf20Sopenharmony_ci * buffer dest. 3908c2ecf20Sopenharmony_ci * Delete cpy_num - del_par items and node pointers from buffer src. 3918c2ecf20Sopenharmony_ci * last_first == FIRST_TO_LAST means, that we copy/delete first items from src. 3928c2ecf20Sopenharmony_ci * last_first == LAST_TO_FIRST means, that we copy/delete last items from src. 3938c2ecf20Sopenharmony_ci */ 3948c2ecf20Sopenharmony_cistatic void internal_move_pointers_items(struct buffer_info *dest_bi, 3958c2ecf20Sopenharmony_ci struct buffer_info *src_bi, 3968c2ecf20Sopenharmony_ci int last_first, int cpy_num, 3978c2ecf20Sopenharmony_ci int del_par) 3988c2ecf20Sopenharmony_ci{ 3998c2ecf20Sopenharmony_ci int first_pointer; 4008c2ecf20Sopenharmony_ci int first_item; 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_ci internal_copy_pointers_items(dest_bi, src_bi->bi_bh, last_first, 4038c2ecf20Sopenharmony_ci cpy_num); 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_ci if (last_first == FIRST_TO_LAST) { /* shift_left occurs */ 4068c2ecf20Sopenharmony_ci first_pointer = 0; 4078c2ecf20Sopenharmony_ci first_item = 0; 4088c2ecf20Sopenharmony_ci /* 4098c2ecf20Sopenharmony_ci * delete cpy_num - del_par pointers and keys starting for 4108c2ecf20Sopenharmony_ci * pointers with first_pointer, for key - with first_item 4118c2ecf20Sopenharmony_ci */ 4128c2ecf20Sopenharmony_ci internal_delete_pointers_items(src_bi, first_pointer, 4138c2ecf20Sopenharmony_ci first_item, cpy_num - del_par); 4148c2ecf20Sopenharmony_ci } else { /* shift_right occurs */ 4158c2ecf20Sopenharmony_ci int i, j; 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_ci i = (cpy_num - del_par == 4188c2ecf20Sopenharmony_ci (j = 4198c2ecf20Sopenharmony_ci B_NR_ITEMS(src_bi->bi_bh)) + 1) ? 0 : j - cpy_num + 4208c2ecf20Sopenharmony_ci del_par; 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_ci internal_delete_pointers_items(src_bi, 4238c2ecf20Sopenharmony_ci j + 1 - cpy_num + del_par, i, 4248c2ecf20Sopenharmony_ci cpy_num - del_par); 4258c2ecf20Sopenharmony_ci } 4268c2ecf20Sopenharmony_ci} 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_ci/* Insert n_src'th key of buffer src before n_dest'th key of buffer dest. */ 4298c2ecf20Sopenharmony_cistatic void internal_insert_key(struct buffer_info *dest_bi, 4308c2ecf20Sopenharmony_ci /* insert key before key with n_dest number */ 4318c2ecf20Sopenharmony_ci int dest_position_before, 4328c2ecf20Sopenharmony_ci struct buffer_head *src, int src_position) 4338c2ecf20Sopenharmony_ci{ 4348c2ecf20Sopenharmony_ci struct buffer_head *dest = dest_bi->bi_bh; 4358c2ecf20Sopenharmony_ci int nr; 4368c2ecf20Sopenharmony_ci struct block_head *blkh; 4378c2ecf20Sopenharmony_ci struct reiserfs_key *key; 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ci RFALSE(dest == NULL || src == NULL, 4408c2ecf20Sopenharmony_ci "source(%p) or dest(%p) buffer is 0", src, dest); 4418c2ecf20Sopenharmony_ci RFALSE(dest_position_before < 0 || src_position < 0, 4428c2ecf20Sopenharmony_ci "source(%d) or dest(%d) key number less than 0", 4438c2ecf20Sopenharmony_ci src_position, dest_position_before); 4448c2ecf20Sopenharmony_ci RFALSE(dest_position_before > B_NR_ITEMS(dest) || 4458c2ecf20Sopenharmony_ci src_position >= B_NR_ITEMS(src), 4468c2ecf20Sopenharmony_ci "invalid position in dest (%d (key number %d)) or in src (%d (key number %d))", 4478c2ecf20Sopenharmony_ci dest_position_before, B_NR_ITEMS(dest), 4488c2ecf20Sopenharmony_ci src_position, B_NR_ITEMS(src)); 4498c2ecf20Sopenharmony_ci RFALSE(B_FREE_SPACE(dest) < KEY_SIZE, 4508c2ecf20Sopenharmony_ci "no enough free space (%d) in dest buffer", B_FREE_SPACE(dest)); 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_ci blkh = B_BLK_HEAD(dest); 4538c2ecf20Sopenharmony_ci nr = blkh_nr_item(blkh); 4548c2ecf20Sopenharmony_ci 4558c2ecf20Sopenharmony_ci /* prepare space for inserting key */ 4568c2ecf20Sopenharmony_ci key = internal_key(dest, dest_position_before); 4578c2ecf20Sopenharmony_ci memmove(key + 1, key, 4588c2ecf20Sopenharmony_ci (nr - dest_position_before) * KEY_SIZE + (nr + 1) * DC_SIZE); 4598c2ecf20Sopenharmony_ci 4608c2ecf20Sopenharmony_ci /* insert key */ 4618c2ecf20Sopenharmony_ci memcpy(key, internal_key(src, src_position), KEY_SIZE); 4628c2ecf20Sopenharmony_ci 4638c2ecf20Sopenharmony_ci /* Change dirt, free space, item number fields. */ 4648c2ecf20Sopenharmony_ci 4658c2ecf20Sopenharmony_ci set_blkh_nr_item(blkh, blkh_nr_item(blkh) + 1); 4668c2ecf20Sopenharmony_ci set_blkh_free_space(blkh, blkh_free_space(blkh) - KEY_SIZE); 4678c2ecf20Sopenharmony_ci 4688c2ecf20Sopenharmony_ci do_balance_mark_internal_dirty(dest_bi->tb, dest, 0); 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_ci if (dest_bi->bi_parent) { 4718c2ecf20Sopenharmony_ci struct disk_child *t_dc; 4728c2ecf20Sopenharmony_ci t_dc = B_N_CHILD(dest_bi->bi_parent, dest_bi->bi_position); 4738c2ecf20Sopenharmony_ci put_dc_size(t_dc, dc_size(t_dc) + KEY_SIZE); 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_ci do_balance_mark_internal_dirty(dest_bi->tb, dest_bi->bi_parent, 4768c2ecf20Sopenharmony_ci 0); 4778c2ecf20Sopenharmony_ci } 4788c2ecf20Sopenharmony_ci} 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_ci/* 4818c2ecf20Sopenharmony_ci * Insert d_key'th (delimiting) key from buffer cfl to tail of dest. 4828c2ecf20Sopenharmony_ci * Copy pointer_amount node pointers and pointer_amount - 1 items from 4838c2ecf20Sopenharmony_ci * buffer src to buffer dest. 4848c2ecf20Sopenharmony_ci * Replace d_key'th key in buffer cfl. 4858c2ecf20Sopenharmony_ci * Delete pointer_amount items and node pointers from buffer src. 4868c2ecf20Sopenharmony_ci */ 4878c2ecf20Sopenharmony_ci/* this can be invoked both to shift from S to L and from R to S */ 4888c2ecf20Sopenharmony_cistatic void internal_shift_left( 4898c2ecf20Sopenharmony_ci /* 4908c2ecf20Sopenharmony_ci * INTERNAL_FROM_S_TO_L | INTERNAL_FROM_R_TO_S 4918c2ecf20Sopenharmony_ci */ 4928c2ecf20Sopenharmony_ci int mode, 4938c2ecf20Sopenharmony_ci struct tree_balance *tb, 4948c2ecf20Sopenharmony_ci int h, int pointer_amount) 4958c2ecf20Sopenharmony_ci{ 4968c2ecf20Sopenharmony_ci struct buffer_info dest_bi, src_bi; 4978c2ecf20Sopenharmony_ci struct buffer_head *cf; 4988c2ecf20Sopenharmony_ci int d_key_position; 4998c2ecf20Sopenharmony_ci 5008c2ecf20Sopenharmony_ci internal_define_dest_src_infos(mode, tb, h, &dest_bi, &src_bi, 5018c2ecf20Sopenharmony_ci &d_key_position, &cf); 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_ci /*printk("pointer_amount = %d\n",pointer_amount); */ 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci if (pointer_amount) { 5068c2ecf20Sopenharmony_ci /* 5078c2ecf20Sopenharmony_ci * insert delimiting key from common father of dest and 5088c2ecf20Sopenharmony_ci * src to node dest into position B_NR_ITEM(dest) 5098c2ecf20Sopenharmony_ci */ 5108c2ecf20Sopenharmony_ci internal_insert_key(&dest_bi, B_NR_ITEMS(dest_bi.bi_bh), cf, 5118c2ecf20Sopenharmony_ci d_key_position); 5128c2ecf20Sopenharmony_ci 5138c2ecf20Sopenharmony_ci if (B_NR_ITEMS(src_bi.bi_bh) == pointer_amount - 1) { 5148c2ecf20Sopenharmony_ci if (src_bi.bi_position /*src->b_item_order */ == 0) 5158c2ecf20Sopenharmony_ci replace_key(tb, cf, d_key_position, 5168c2ecf20Sopenharmony_ci src_bi. 5178c2ecf20Sopenharmony_ci bi_parent /*src->b_parent */ , 0); 5188c2ecf20Sopenharmony_ci } else 5198c2ecf20Sopenharmony_ci replace_key(tb, cf, d_key_position, src_bi.bi_bh, 5208c2ecf20Sopenharmony_ci pointer_amount - 1); 5218c2ecf20Sopenharmony_ci } 5228c2ecf20Sopenharmony_ci /* last parameter is del_parameter */ 5238c2ecf20Sopenharmony_ci internal_move_pointers_items(&dest_bi, &src_bi, FIRST_TO_LAST, 5248c2ecf20Sopenharmony_ci pointer_amount, 0); 5258c2ecf20Sopenharmony_ci 5268c2ecf20Sopenharmony_ci} 5278c2ecf20Sopenharmony_ci 5288c2ecf20Sopenharmony_ci/* 5298c2ecf20Sopenharmony_ci * Insert delimiting key to L[h]. 5308c2ecf20Sopenharmony_ci * Copy n node pointers and n - 1 items from buffer S[h] to L[h]. 5318c2ecf20Sopenharmony_ci * Delete n - 1 items and node pointers from buffer S[h]. 5328c2ecf20Sopenharmony_ci */ 5338c2ecf20Sopenharmony_ci/* it always shifts from S[h] to L[h] */ 5348c2ecf20Sopenharmony_cistatic void internal_shift1_left(struct tree_balance *tb, 5358c2ecf20Sopenharmony_ci int h, int pointer_amount) 5368c2ecf20Sopenharmony_ci{ 5378c2ecf20Sopenharmony_ci struct buffer_info dest_bi, src_bi; 5388c2ecf20Sopenharmony_ci struct buffer_head *cf; 5398c2ecf20Sopenharmony_ci int d_key_position; 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_ci internal_define_dest_src_infos(INTERNAL_SHIFT_FROM_S_TO_L, tb, h, 5428c2ecf20Sopenharmony_ci &dest_bi, &src_bi, &d_key_position, &cf); 5438c2ecf20Sopenharmony_ci 5448c2ecf20Sopenharmony_ci /* insert lkey[h]-th key from CFL[h] to left neighbor L[h] */ 5458c2ecf20Sopenharmony_ci if (pointer_amount > 0) 5468c2ecf20Sopenharmony_ci internal_insert_key(&dest_bi, B_NR_ITEMS(dest_bi.bi_bh), cf, 5478c2ecf20Sopenharmony_ci d_key_position); 5488c2ecf20Sopenharmony_ci 5498c2ecf20Sopenharmony_ci /* last parameter is del_parameter */ 5508c2ecf20Sopenharmony_ci internal_move_pointers_items(&dest_bi, &src_bi, FIRST_TO_LAST, 5518c2ecf20Sopenharmony_ci pointer_amount, 1); 5528c2ecf20Sopenharmony_ci} 5538c2ecf20Sopenharmony_ci 5548c2ecf20Sopenharmony_ci/* 5558c2ecf20Sopenharmony_ci * Insert d_key'th (delimiting) key from buffer cfr to head of dest. 5568c2ecf20Sopenharmony_ci * Copy n node pointers and n - 1 items from buffer src to buffer dest. 5578c2ecf20Sopenharmony_ci * Replace d_key'th key in buffer cfr. 5588c2ecf20Sopenharmony_ci * Delete n items and node pointers from buffer src. 5598c2ecf20Sopenharmony_ci */ 5608c2ecf20Sopenharmony_cistatic void internal_shift_right( 5618c2ecf20Sopenharmony_ci /* 5628c2ecf20Sopenharmony_ci * INTERNAL_FROM_S_TO_R | INTERNAL_FROM_L_TO_S 5638c2ecf20Sopenharmony_ci */ 5648c2ecf20Sopenharmony_ci int mode, 5658c2ecf20Sopenharmony_ci struct tree_balance *tb, 5668c2ecf20Sopenharmony_ci int h, int pointer_amount) 5678c2ecf20Sopenharmony_ci{ 5688c2ecf20Sopenharmony_ci struct buffer_info dest_bi, src_bi; 5698c2ecf20Sopenharmony_ci struct buffer_head *cf; 5708c2ecf20Sopenharmony_ci int d_key_position; 5718c2ecf20Sopenharmony_ci int nr; 5728c2ecf20Sopenharmony_ci 5738c2ecf20Sopenharmony_ci internal_define_dest_src_infos(mode, tb, h, &dest_bi, &src_bi, 5748c2ecf20Sopenharmony_ci &d_key_position, &cf); 5758c2ecf20Sopenharmony_ci 5768c2ecf20Sopenharmony_ci nr = B_NR_ITEMS(src_bi.bi_bh); 5778c2ecf20Sopenharmony_ci 5788c2ecf20Sopenharmony_ci if (pointer_amount > 0) { 5798c2ecf20Sopenharmony_ci /* 5808c2ecf20Sopenharmony_ci * insert delimiting key from common father of dest 5818c2ecf20Sopenharmony_ci * and src to dest node into position 0 5828c2ecf20Sopenharmony_ci */ 5838c2ecf20Sopenharmony_ci internal_insert_key(&dest_bi, 0, cf, d_key_position); 5848c2ecf20Sopenharmony_ci if (nr == pointer_amount - 1) { 5858c2ecf20Sopenharmony_ci RFALSE(src_bi.bi_bh != PATH_H_PBUFFER(tb->tb_path, h) /*tb->S[h] */ || 5868c2ecf20Sopenharmony_ci dest_bi.bi_bh != tb->R[h], 5878c2ecf20Sopenharmony_ci "src (%p) must be == tb->S[h](%p) when it disappears", 5888c2ecf20Sopenharmony_ci src_bi.bi_bh, PATH_H_PBUFFER(tb->tb_path, h)); 5898c2ecf20Sopenharmony_ci /* when S[h] disappers replace left delemiting key as well */ 5908c2ecf20Sopenharmony_ci if (tb->CFL[h]) 5918c2ecf20Sopenharmony_ci replace_key(tb, cf, d_key_position, tb->CFL[h], 5928c2ecf20Sopenharmony_ci tb->lkey[h]); 5938c2ecf20Sopenharmony_ci } else 5948c2ecf20Sopenharmony_ci replace_key(tb, cf, d_key_position, src_bi.bi_bh, 5958c2ecf20Sopenharmony_ci nr - pointer_amount); 5968c2ecf20Sopenharmony_ci } 5978c2ecf20Sopenharmony_ci 5988c2ecf20Sopenharmony_ci /* last parameter is del_parameter */ 5998c2ecf20Sopenharmony_ci internal_move_pointers_items(&dest_bi, &src_bi, LAST_TO_FIRST, 6008c2ecf20Sopenharmony_ci pointer_amount, 0); 6018c2ecf20Sopenharmony_ci} 6028c2ecf20Sopenharmony_ci 6038c2ecf20Sopenharmony_ci/* 6048c2ecf20Sopenharmony_ci * Insert delimiting key to R[h]. 6058c2ecf20Sopenharmony_ci * Copy n node pointers and n - 1 items from buffer S[h] to R[h]. 6068c2ecf20Sopenharmony_ci * Delete n - 1 items and node pointers from buffer S[h]. 6078c2ecf20Sopenharmony_ci */ 6088c2ecf20Sopenharmony_ci/* it always shift from S[h] to R[h] */ 6098c2ecf20Sopenharmony_cistatic void internal_shift1_right(struct tree_balance *tb, 6108c2ecf20Sopenharmony_ci int h, int pointer_amount) 6118c2ecf20Sopenharmony_ci{ 6128c2ecf20Sopenharmony_ci struct buffer_info dest_bi, src_bi; 6138c2ecf20Sopenharmony_ci struct buffer_head *cf; 6148c2ecf20Sopenharmony_ci int d_key_position; 6158c2ecf20Sopenharmony_ci 6168c2ecf20Sopenharmony_ci internal_define_dest_src_infos(INTERNAL_SHIFT_FROM_S_TO_R, tb, h, 6178c2ecf20Sopenharmony_ci &dest_bi, &src_bi, &d_key_position, &cf); 6188c2ecf20Sopenharmony_ci 6198c2ecf20Sopenharmony_ci /* insert rkey from CFR[h] to right neighbor R[h] */ 6208c2ecf20Sopenharmony_ci if (pointer_amount > 0) 6218c2ecf20Sopenharmony_ci internal_insert_key(&dest_bi, 0, cf, d_key_position); 6228c2ecf20Sopenharmony_ci 6238c2ecf20Sopenharmony_ci /* last parameter is del_parameter */ 6248c2ecf20Sopenharmony_ci internal_move_pointers_items(&dest_bi, &src_bi, LAST_TO_FIRST, 6258c2ecf20Sopenharmony_ci pointer_amount, 1); 6268c2ecf20Sopenharmony_ci} 6278c2ecf20Sopenharmony_ci 6288c2ecf20Sopenharmony_ci/* 6298c2ecf20Sopenharmony_ci * Delete insert_num node pointers together with their left items 6308c2ecf20Sopenharmony_ci * and balance current node. 6318c2ecf20Sopenharmony_ci */ 6328c2ecf20Sopenharmony_cistatic void balance_internal_when_delete(struct tree_balance *tb, 6338c2ecf20Sopenharmony_ci int h, int child_pos) 6348c2ecf20Sopenharmony_ci{ 6358c2ecf20Sopenharmony_ci int insert_num; 6368c2ecf20Sopenharmony_ci int n; 6378c2ecf20Sopenharmony_ci struct buffer_head *tbSh = PATH_H_PBUFFER(tb->tb_path, h); 6388c2ecf20Sopenharmony_ci struct buffer_info bi; 6398c2ecf20Sopenharmony_ci 6408c2ecf20Sopenharmony_ci insert_num = tb->insert_size[h] / ((int)(DC_SIZE + KEY_SIZE)); 6418c2ecf20Sopenharmony_ci 6428c2ecf20Sopenharmony_ci /* delete child-node-pointer(s) together with their left item(s) */ 6438c2ecf20Sopenharmony_ci bi.tb = tb; 6448c2ecf20Sopenharmony_ci bi.bi_bh = tbSh; 6458c2ecf20Sopenharmony_ci bi.bi_parent = PATH_H_PPARENT(tb->tb_path, h); 6468c2ecf20Sopenharmony_ci bi.bi_position = PATH_H_POSITION(tb->tb_path, h + 1); 6478c2ecf20Sopenharmony_ci 6488c2ecf20Sopenharmony_ci internal_delete_childs(&bi, child_pos, -insert_num); 6498c2ecf20Sopenharmony_ci 6508c2ecf20Sopenharmony_ci RFALSE(tb->blknum[h] > 1, 6518c2ecf20Sopenharmony_ci "tb->blknum[%d]=%d when insert_size < 0", h, tb->blknum[h]); 6528c2ecf20Sopenharmony_ci 6538c2ecf20Sopenharmony_ci n = B_NR_ITEMS(tbSh); 6548c2ecf20Sopenharmony_ci 6558c2ecf20Sopenharmony_ci if (tb->lnum[h] == 0 && tb->rnum[h] == 0) { 6568c2ecf20Sopenharmony_ci if (tb->blknum[h] == 0) { 6578c2ecf20Sopenharmony_ci /* node S[h] (root of the tree) is empty now */ 6588c2ecf20Sopenharmony_ci struct buffer_head *new_root; 6598c2ecf20Sopenharmony_ci 6608c2ecf20Sopenharmony_ci RFALSE(n 6618c2ecf20Sopenharmony_ci || B_FREE_SPACE(tbSh) != 6628c2ecf20Sopenharmony_ci MAX_CHILD_SIZE(tbSh) - DC_SIZE, 6638c2ecf20Sopenharmony_ci "buffer must have only 0 keys (%d)", n); 6648c2ecf20Sopenharmony_ci RFALSE(bi.bi_parent, "root has parent (%p)", 6658c2ecf20Sopenharmony_ci bi.bi_parent); 6668c2ecf20Sopenharmony_ci 6678c2ecf20Sopenharmony_ci /* choose a new root */ 6688c2ecf20Sopenharmony_ci if (!tb->L[h - 1] || !B_NR_ITEMS(tb->L[h - 1])) 6698c2ecf20Sopenharmony_ci new_root = tb->R[h - 1]; 6708c2ecf20Sopenharmony_ci else 6718c2ecf20Sopenharmony_ci new_root = tb->L[h - 1]; 6728c2ecf20Sopenharmony_ci /* 6738c2ecf20Sopenharmony_ci * switch super block's tree root block 6748c2ecf20Sopenharmony_ci * number to the new value */ 6758c2ecf20Sopenharmony_ci PUT_SB_ROOT_BLOCK(tb->tb_sb, new_root->b_blocknr); 6768c2ecf20Sopenharmony_ci /*REISERFS_SB(tb->tb_sb)->s_rs->s_tree_height --; */ 6778c2ecf20Sopenharmony_ci PUT_SB_TREE_HEIGHT(tb->tb_sb, 6788c2ecf20Sopenharmony_ci SB_TREE_HEIGHT(tb->tb_sb) - 1); 6798c2ecf20Sopenharmony_ci 6808c2ecf20Sopenharmony_ci do_balance_mark_sb_dirty(tb, 6818c2ecf20Sopenharmony_ci REISERFS_SB(tb->tb_sb)->s_sbh, 6828c2ecf20Sopenharmony_ci 1); 6838c2ecf20Sopenharmony_ci /*&&&&&&&&&&&&&&&&&&&&&& */ 6848c2ecf20Sopenharmony_ci /* use check_internal if new root is an internal node */ 6858c2ecf20Sopenharmony_ci if (h > 1) 6868c2ecf20Sopenharmony_ci check_internal(new_root); 6878c2ecf20Sopenharmony_ci /*&&&&&&&&&&&&&&&&&&&&&& */ 6888c2ecf20Sopenharmony_ci 6898c2ecf20Sopenharmony_ci /* do what is needed for buffer thrown from tree */ 6908c2ecf20Sopenharmony_ci reiserfs_invalidate_buffer(tb, tbSh); 6918c2ecf20Sopenharmony_ci return; 6928c2ecf20Sopenharmony_ci } 6938c2ecf20Sopenharmony_ci return; 6948c2ecf20Sopenharmony_ci } 6958c2ecf20Sopenharmony_ci 6968c2ecf20Sopenharmony_ci /* join S[h] with L[h] */ 6978c2ecf20Sopenharmony_ci if (tb->L[h] && tb->lnum[h] == -B_NR_ITEMS(tb->L[h]) - 1) { 6988c2ecf20Sopenharmony_ci 6998c2ecf20Sopenharmony_ci RFALSE(tb->rnum[h] != 0, 7008c2ecf20Sopenharmony_ci "invalid tb->rnum[%d]==%d when joining S[h] with L[h]", 7018c2ecf20Sopenharmony_ci h, tb->rnum[h]); 7028c2ecf20Sopenharmony_ci 7038c2ecf20Sopenharmony_ci internal_shift_left(INTERNAL_SHIFT_FROM_S_TO_L, tb, h, n + 1); 7048c2ecf20Sopenharmony_ci reiserfs_invalidate_buffer(tb, tbSh); 7058c2ecf20Sopenharmony_ci 7068c2ecf20Sopenharmony_ci return; 7078c2ecf20Sopenharmony_ci } 7088c2ecf20Sopenharmony_ci 7098c2ecf20Sopenharmony_ci /* join S[h] with R[h] */ 7108c2ecf20Sopenharmony_ci if (tb->R[h] && tb->rnum[h] == -B_NR_ITEMS(tb->R[h]) - 1) { 7118c2ecf20Sopenharmony_ci RFALSE(tb->lnum[h] != 0, 7128c2ecf20Sopenharmony_ci "invalid tb->lnum[%d]==%d when joining S[h] with R[h]", 7138c2ecf20Sopenharmony_ci h, tb->lnum[h]); 7148c2ecf20Sopenharmony_ci 7158c2ecf20Sopenharmony_ci internal_shift_right(INTERNAL_SHIFT_FROM_S_TO_R, tb, h, n + 1); 7168c2ecf20Sopenharmony_ci 7178c2ecf20Sopenharmony_ci reiserfs_invalidate_buffer(tb, tbSh); 7188c2ecf20Sopenharmony_ci return; 7198c2ecf20Sopenharmony_ci } 7208c2ecf20Sopenharmony_ci 7218c2ecf20Sopenharmony_ci /* borrow from left neighbor L[h] */ 7228c2ecf20Sopenharmony_ci if (tb->lnum[h] < 0) { 7238c2ecf20Sopenharmony_ci RFALSE(tb->rnum[h] != 0, 7248c2ecf20Sopenharmony_ci "wrong tb->rnum[%d]==%d when borrow from L[h]", h, 7258c2ecf20Sopenharmony_ci tb->rnum[h]); 7268c2ecf20Sopenharmony_ci internal_shift_right(INTERNAL_SHIFT_FROM_L_TO_S, tb, h, 7278c2ecf20Sopenharmony_ci -tb->lnum[h]); 7288c2ecf20Sopenharmony_ci return; 7298c2ecf20Sopenharmony_ci } 7308c2ecf20Sopenharmony_ci 7318c2ecf20Sopenharmony_ci /* borrow from right neighbor R[h] */ 7328c2ecf20Sopenharmony_ci if (tb->rnum[h] < 0) { 7338c2ecf20Sopenharmony_ci RFALSE(tb->lnum[h] != 0, 7348c2ecf20Sopenharmony_ci "invalid tb->lnum[%d]==%d when borrow from R[h]", 7358c2ecf20Sopenharmony_ci h, tb->lnum[h]); 7368c2ecf20Sopenharmony_ci internal_shift_left(INTERNAL_SHIFT_FROM_R_TO_S, tb, h, -tb->rnum[h]); /*tb->S[h], tb->CFR[h], tb->rkey[h], tb->R[h], -tb->rnum[h]); */ 7378c2ecf20Sopenharmony_ci return; 7388c2ecf20Sopenharmony_ci } 7398c2ecf20Sopenharmony_ci 7408c2ecf20Sopenharmony_ci /* split S[h] into two parts and put them into neighbors */ 7418c2ecf20Sopenharmony_ci if (tb->lnum[h] > 0) { 7428c2ecf20Sopenharmony_ci RFALSE(tb->rnum[h] == 0 || tb->lnum[h] + tb->rnum[h] != n + 1, 7438c2ecf20Sopenharmony_ci "invalid tb->lnum[%d]==%d or tb->rnum[%d]==%d when S[h](item number == %d) is split between them", 7448c2ecf20Sopenharmony_ci h, tb->lnum[h], h, tb->rnum[h], n); 7458c2ecf20Sopenharmony_ci 7468c2ecf20Sopenharmony_ci internal_shift_left(INTERNAL_SHIFT_FROM_S_TO_L, tb, h, tb->lnum[h]); /*tb->L[h], tb->CFL[h], tb->lkey[h], tb->S[h], tb->lnum[h]); */ 7478c2ecf20Sopenharmony_ci internal_shift_right(INTERNAL_SHIFT_FROM_S_TO_R, tb, h, 7488c2ecf20Sopenharmony_ci tb->rnum[h]); 7498c2ecf20Sopenharmony_ci 7508c2ecf20Sopenharmony_ci reiserfs_invalidate_buffer(tb, tbSh); 7518c2ecf20Sopenharmony_ci 7528c2ecf20Sopenharmony_ci return; 7538c2ecf20Sopenharmony_ci } 7548c2ecf20Sopenharmony_ci reiserfs_panic(tb->tb_sb, "ibalance-2", 7558c2ecf20Sopenharmony_ci "unexpected tb->lnum[%d]==%d or tb->rnum[%d]==%d", 7568c2ecf20Sopenharmony_ci h, tb->lnum[h], h, tb->rnum[h]); 7578c2ecf20Sopenharmony_ci} 7588c2ecf20Sopenharmony_ci 7598c2ecf20Sopenharmony_ci/* Replace delimiting key of buffers L[h] and S[h] by the given key.*/ 7608c2ecf20Sopenharmony_cistatic void replace_lkey(struct tree_balance *tb, int h, struct item_head *key) 7618c2ecf20Sopenharmony_ci{ 7628c2ecf20Sopenharmony_ci RFALSE(tb->L[h] == NULL || tb->CFL[h] == NULL, 7638c2ecf20Sopenharmony_ci "L[h](%p) and CFL[h](%p) must exist in replace_lkey", 7648c2ecf20Sopenharmony_ci tb->L[h], tb->CFL[h]); 7658c2ecf20Sopenharmony_ci 7668c2ecf20Sopenharmony_ci if (B_NR_ITEMS(PATH_H_PBUFFER(tb->tb_path, h)) == 0) 7678c2ecf20Sopenharmony_ci return; 7688c2ecf20Sopenharmony_ci 7698c2ecf20Sopenharmony_ci memcpy(internal_key(tb->CFL[h], tb->lkey[h]), key, KEY_SIZE); 7708c2ecf20Sopenharmony_ci 7718c2ecf20Sopenharmony_ci do_balance_mark_internal_dirty(tb, tb->CFL[h], 0); 7728c2ecf20Sopenharmony_ci} 7738c2ecf20Sopenharmony_ci 7748c2ecf20Sopenharmony_ci/* Replace delimiting key of buffers S[h] and R[h] by the given key.*/ 7758c2ecf20Sopenharmony_cistatic void replace_rkey(struct tree_balance *tb, int h, struct item_head *key) 7768c2ecf20Sopenharmony_ci{ 7778c2ecf20Sopenharmony_ci RFALSE(tb->R[h] == NULL || tb->CFR[h] == NULL, 7788c2ecf20Sopenharmony_ci "R[h](%p) and CFR[h](%p) must exist in replace_rkey", 7798c2ecf20Sopenharmony_ci tb->R[h], tb->CFR[h]); 7808c2ecf20Sopenharmony_ci RFALSE(B_NR_ITEMS(tb->R[h]) == 0, 7818c2ecf20Sopenharmony_ci "R[h] can not be empty if it exists (item number=%d)", 7828c2ecf20Sopenharmony_ci B_NR_ITEMS(tb->R[h])); 7838c2ecf20Sopenharmony_ci 7848c2ecf20Sopenharmony_ci memcpy(internal_key(tb->CFR[h], tb->rkey[h]), key, KEY_SIZE); 7858c2ecf20Sopenharmony_ci 7868c2ecf20Sopenharmony_ci do_balance_mark_internal_dirty(tb, tb->CFR[h], 0); 7878c2ecf20Sopenharmony_ci} 7888c2ecf20Sopenharmony_ci 7898c2ecf20Sopenharmony_ci 7908c2ecf20Sopenharmony_ci/* 7918c2ecf20Sopenharmony_ci * if inserting/pasting { 7928c2ecf20Sopenharmony_ci * child_pos is the position of the node-pointer in S[h] that 7938c2ecf20Sopenharmony_ci * pointed to S[h-1] before balancing of the h-1 level; 7948c2ecf20Sopenharmony_ci * this means that new pointers and items must be inserted AFTER 7958c2ecf20Sopenharmony_ci * child_pos 7968c2ecf20Sopenharmony_ci * } else { 7978c2ecf20Sopenharmony_ci * it is the position of the leftmost pointer that must be deleted 7988c2ecf20Sopenharmony_ci * (together with its corresponding key to the left of the pointer) 7998c2ecf20Sopenharmony_ci * as a result of the previous level's balancing. 8008c2ecf20Sopenharmony_ci * } 8018c2ecf20Sopenharmony_ci */ 8028c2ecf20Sopenharmony_ci 8038c2ecf20Sopenharmony_ciint balance_internal(struct tree_balance *tb, 8048c2ecf20Sopenharmony_ci int h, /* level of the tree */ 8058c2ecf20Sopenharmony_ci int child_pos, 8068c2ecf20Sopenharmony_ci /* key for insertion on higher level */ 8078c2ecf20Sopenharmony_ci struct item_head *insert_key, 8088c2ecf20Sopenharmony_ci /* node for insertion on higher level */ 8098c2ecf20Sopenharmony_ci struct buffer_head **insert_ptr) 8108c2ecf20Sopenharmony_ci{ 8118c2ecf20Sopenharmony_ci struct buffer_head *tbSh = PATH_H_PBUFFER(tb->tb_path, h); 8128c2ecf20Sopenharmony_ci struct buffer_info bi; 8138c2ecf20Sopenharmony_ci 8148c2ecf20Sopenharmony_ci /* 8158c2ecf20Sopenharmony_ci * we return this: it is 0 if there is no S[h], 8168c2ecf20Sopenharmony_ci * else it is tb->S[h]->b_item_order 8178c2ecf20Sopenharmony_ci */ 8188c2ecf20Sopenharmony_ci int order; 8198c2ecf20Sopenharmony_ci int insert_num, n, k; 8208c2ecf20Sopenharmony_ci struct buffer_head *S_new; 8218c2ecf20Sopenharmony_ci struct item_head new_insert_key; 8228c2ecf20Sopenharmony_ci struct buffer_head *new_insert_ptr = NULL; 8238c2ecf20Sopenharmony_ci struct item_head *new_insert_key_addr = insert_key; 8248c2ecf20Sopenharmony_ci 8258c2ecf20Sopenharmony_ci RFALSE(h < 1, "h (%d) can not be < 1 on internal level", h); 8268c2ecf20Sopenharmony_ci 8278c2ecf20Sopenharmony_ci PROC_INFO_INC(tb->tb_sb, balance_at[h]); 8288c2ecf20Sopenharmony_ci 8298c2ecf20Sopenharmony_ci order = 8308c2ecf20Sopenharmony_ci (tbSh) ? PATH_H_POSITION(tb->tb_path, 8318c2ecf20Sopenharmony_ci h + 1) /*tb->S[h]->b_item_order */ : 0; 8328c2ecf20Sopenharmony_ci 8338c2ecf20Sopenharmony_ci /* 8348c2ecf20Sopenharmony_ci * Using insert_size[h] calculate the number insert_num of items 8358c2ecf20Sopenharmony_ci * that must be inserted to or deleted from S[h]. 8368c2ecf20Sopenharmony_ci */ 8378c2ecf20Sopenharmony_ci insert_num = tb->insert_size[h] / ((int)(KEY_SIZE + DC_SIZE)); 8388c2ecf20Sopenharmony_ci 8398c2ecf20Sopenharmony_ci /* Check whether insert_num is proper * */ 8408c2ecf20Sopenharmony_ci RFALSE(insert_num < -2 || insert_num > 2, 8418c2ecf20Sopenharmony_ci "incorrect number of items inserted to the internal node (%d)", 8428c2ecf20Sopenharmony_ci insert_num); 8438c2ecf20Sopenharmony_ci RFALSE(h > 1 && (insert_num > 1 || insert_num < -1), 8448c2ecf20Sopenharmony_ci "incorrect number of items (%d) inserted to the internal node on a level (h=%d) higher than last internal level", 8458c2ecf20Sopenharmony_ci insert_num, h); 8468c2ecf20Sopenharmony_ci 8478c2ecf20Sopenharmony_ci /* Make balance in case insert_num < 0 */ 8488c2ecf20Sopenharmony_ci if (insert_num < 0) { 8498c2ecf20Sopenharmony_ci balance_internal_when_delete(tb, h, child_pos); 8508c2ecf20Sopenharmony_ci return order; 8518c2ecf20Sopenharmony_ci } 8528c2ecf20Sopenharmony_ci 8538c2ecf20Sopenharmony_ci k = 0; 8548c2ecf20Sopenharmony_ci if (tb->lnum[h] > 0) { 8558c2ecf20Sopenharmony_ci /* 8568c2ecf20Sopenharmony_ci * shift lnum[h] items from S[h] to the left neighbor L[h]. 8578c2ecf20Sopenharmony_ci * check how many of new items fall into L[h] or CFL[h] after 8588c2ecf20Sopenharmony_ci * shifting 8598c2ecf20Sopenharmony_ci */ 8608c2ecf20Sopenharmony_ci n = B_NR_ITEMS(tb->L[h]); /* number of items in L[h] */ 8618c2ecf20Sopenharmony_ci if (tb->lnum[h] <= child_pos) { 8628c2ecf20Sopenharmony_ci /* new items don't fall into L[h] or CFL[h] */ 8638c2ecf20Sopenharmony_ci internal_shift_left(INTERNAL_SHIFT_FROM_S_TO_L, tb, h, 8648c2ecf20Sopenharmony_ci tb->lnum[h]); 8658c2ecf20Sopenharmony_ci child_pos -= tb->lnum[h]; 8668c2ecf20Sopenharmony_ci } else if (tb->lnum[h] > child_pos + insert_num) { 8678c2ecf20Sopenharmony_ci /* all new items fall into L[h] */ 8688c2ecf20Sopenharmony_ci internal_shift_left(INTERNAL_SHIFT_FROM_S_TO_L, tb, h, 8698c2ecf20Sopenharmony_ci tb->lnum[h] - insert_num); 8708c2ecf20Sopenharmony_ci /* insert insert_num keys and node-pointers into L[h] */ 8718c2ecf20Sopenharmony_ci bi.tb = tb; 8728c2ecf20Sopenharmony_ci bi.bi_bh = tb->L[h]; 8738c2ecf20Sopenharmony_ci bi.bi_parent = tb->FL[h]; 8748c2ecf20Sopenharmony_ci bi.bi_position = get_left_neighbor_position(tb, h); 8758c2ecf20Sopenharmony_ci internal_insert_childs(&bi, 8768c2ecf20Sopenharmony_ci /*tb->L[h], tb->S[h-1]->b_next */ 8778c2ecf20Sopenharmony_ci n + child_pos + 1, 8788c2ecf20Sopenharmony_ci insert_num, insert_key, 8798c2ecf20Sopenharmony_ci insert_ptr); 8808c2ecf20Sopenharmony_ci 8818c2ecf20Sopenharmony_ci insert_num = 0; 8828c2ecf20Sopenharmony_ci } else { 8838c2ecf20Sopenharmony_ci struct disk_child *dc; 8848c2ecf20Sopenharmony_ci 8858c2ecf20Sopenharmony_ci /* 8868c2ecf20Sopenharmony_ci * some items fall into L[h] or CFL[h], 8878c2ecf20Sopenharmony_ci * but some don't fall 8888c2ecf20Sopenharmony_ci */ 8898c2ecf20Sopenharmony_ci internal_shift1_left(tb, h, child_pos + 1); 8908c2ecf20Sopenharmony_ci /* calculate number of new items that fall into L[h] */ 8918c2ecf20Sopenharmony_ci k = tb->lnum[h] - child_pos - 1; 8928c2ecf20Sopenharmony_ci bi.tb = tb; 8938c2ecf20Sopenharmony_ci bi.bi_bh = tb->L[h]; 8948c2ecf20Sopenharmony_ci bi.bi_parent = tb->FL[h]; 8958c2ecf20Sopenharmony_ci bi.bi_position = get_left_neighbor_position(tb, h); 8968c2ecf20Sopenharmony_ci internal_insert_childs(&bi, 8978c2ecf20Sopenharmony_ci /*tb->L[h], tb->S[h-1]->b_next, */ 8988c2ecf20Sopenharmony_ci n + child_pos + 1, k, 8998c2ecf20Sopenharmony_ci insert_key, insert_ptr); 9008c2ecf20Sopenharmony_ci 9018c2ecf20Sopenharmony_ci replace_lkey(tb, h, insert_key + k); 9028c2ecf20Sopenharmony_ci 9038c2ecf20Sopenharmony_ci /* 9048c2ecf20Sopenharmony_ci * replace the first node-ptr in S[h] by 9058c2ecf20Sopenharmony_ci * node-ptr to insert_ptr[k] 9068c2ecf20Sopenharmony_ci */ 9078c2ecf20Sopenharmony_ci dc = B_N_CHILD(tbSh, 0); 9088c2ecf20Sopenharmony_ci put_dc_size(dc, 9098c2ecf20Sopenharmony_ci MAX_CHILD_SIZE(insert_ptr[k]) - 9108c2ecf20Sopenharmony_ci B_FREE_SPACE(insert_ptr[k])); 9118c2ecf20Sopenharmony_ci put_dc_block_number(dc, insert_ptr[k]->b_blocknr); 9128c2ecf20Sopenharmony_ci 9138c2ecf20Sopenharmony_ci do_balance_mark_internal_dirty(tb, tbSh, 0); 9148c2ecf20Sopenharmony_ci 9158c2ecf20Sopenharmony_ci k++; 9168c2ecf20Sopenharmony_ci insert_key += k; 9178c2ecf20Sopenharmony_ci insert_ptr += k; 9188c2ecf20Sopenharmony_ci insert_num -= k; 9198c2ecf20Sopenharmony_ci child_pos = 0; 9208c2ecf20Sopenharmony_ci } 9218c2ecf20Sopenharmony_ci } 9228c2ecf20Sopenharmony_ci /* tb->lnum[h] > 0 */ 9238c2ecf20Sopenharmony_ci if (tb->rnum[h] > 0) { 9248c2ecf20Sopenharmony_ci /*shift rnum[h] items from S[h] to the right neighbor R[h] */ 9258c2ecf20Sopenharmony_ci /* 9268c2ecf20Sopenharmony_ci * check how many of new items fall into R or CFR 9278c2ecf20Sopenharmony_ci * after shifting 9288c2ecf20Sopenharmony_ci */ 9298c2ecf20Sopenharmony_ci n = B_NR_ITEMS(tbSh); /* number of items in S[h] */ 9308c2ecf20Sopenharmony_ci if (n - tb->rnum[h] >= child_pos) 9318c2ecf20Sopenharmony_ci /* new items fall into S[h] */ 9328c2ecf20Sopenharmony_ci internal_shift_right(INTERNAL_SHIFT_FROM_S_TO_R, tb, h, 9338c2ecf20Sopenharmony_ci tb->rnum[h]); 9348c2ecf20Sopenharmony_ci else if (n + insert_num - tb->rnum[h] < child_pos) { 9358c2ecf20Sopenharmony_ci /* all new items fall into R[h] */ 9368c2ecf20Sopenharmony_ci internal_shift_right(INTERNAL_SHIFT_FROM_S_TO_R, tb, h, 9378c2ecf20Sopenharmony_ci tb->rnum[h] - insert_num); 9388c2ecf20Sopenharmony_ci 9398c2ecf20Sopenharmony_ci /* insert insert_num keys and node-pointers into R[h] */ 9408c2ecf20Sopenharmony_ci bi.tb = tb; 9418c2ecf20Sopenharmony_ci bi.bi_bh = tb->R[h]; 9428c2ecf20Sopenharmony_ci bi.bi_parent = tb->FR[h]; 9438c2ecf20Sopenharmony_ci bi.bi_position = get_right_neighbor_position(tb, h); 9448c2ecf20Sopenharmony_ci internal_insert_childs(&bi, 9458c2ecf20Sopenharmony_ci /*tb->R[h],tb->S[h-1]->b_next */ 9468c2ecf20Sopenharmony_ci child_pos - n - insert_num + 9478c2ecf20Sopenharmony_ci tb->rnum[h] - 1, 9488c2ecf20Sopenharmony_ci insert_num, insert_key, 9498c2ecf20Sopenharmony_ci insert_ptr); 9508c2ecf20Sopenharmony_ci insert_num = 0; 9518c2ecf20Sopenharmony_ci } else { 9528c2ecf20Sopenharmony_ci struct disk_child *dc; 9538c2ecf20Sopenharmony_ci 9548c2ecf20Sopenharmony_ci /* one of the items falls into CFR[h] */ 9558c2ecf20Sopenharmony_ci internal_shift1_right(tb, h, n - child_pos + 1); 9568c2ecf20Sopenharmony_ci /* calculate number of new items that fall into R[h] */ 9578c2ecf20Sopenharmony_ci k = tb->rnum[h] - n + child_pos - 1; 9588c2ecf20Sopenharmony_ci bi.tb = tb; 9598c2ecf20Sopenharmony_ci bi.bi_bh = tb->R[h]; 9608c2ecf20Sopenharmony_ci bi.bi_parent = tb->FR[h]; 9618c2ecf20Sopenharmony_ci bi.bi_position = get_right_neighbor_position(tb, h); 9628c2ecf20Sopenharmony_ci internal_insert_childs(&bi, 9638c2ecf20Sopenharmony_ci /*tb->R[h], tb->R[h]->b_child, */ 9648c2ecf20Sopenharmony_ci 0, k, insert_key + 1, 9658c2ecf20Sopenharmony_ci insert_ptr + 1); 9668c2ecf20Sopenharmony_ci 9678c2ecf20Sopenharmony_ci replace_rkey(tb, h, insert_key + insert_num - k - 1); 9688c2ecf20Sopenharmony_ci 9698c2ecf20Sopenharmony_ci /* 9708c2ecf20Sopenharmony_ci * replace the first node-ptr in R[h] by 9718c2ecf20Sopenharmony_ci * node-ptr insert_ptr[insert_num-k-1] 9728c2ecf20Sopenharmony_ci */ 9738c2ecf20Sopenharmony_ci dc = B_N_CHILD(tb->R[h], 0); 9748c2ecf20Sopenharmony_ci put_dc_size(dc, 9758c2ecf20Sopenharmony_ci MAX_CHILD_SIZE(insert_ptr 9768c2ecf20Sopenharmony_ci [insert_num - k - 1]) - 9778c2ecf20Sopenharmony_ci B_FREE_SPACE(insert_ptr 9788c2ecf20Sopenharmony_ci [insert_num - k - 1])); 9798c2ecf20Sopenharmony_ci put_dc_block_number(dc, 9808c2ecf20Sopenharmony_ci insert_ptr[insert_num - k - 9818c2ecf20Sopenharmony_ci 1]->b_blocknr); 9828c2ecf20Sopenharmony_ci 9838c2ecf20Sopenharmony_ci do_balance_mark_internal_dirty(tb, tb->R[h], 0); 9848c2ecf20Sopenharmony_ci 9858c2ecf20Sopenharmony_ci insert_num -= (k + 1); 9868c2ecf20Sopenharmony_ci } 9878c2ecf20Sopenharmony_ci } 9888c2ecf20Sopenharmony_ci 9898c2ecf20Sopenharmony_ci /** Fill new node that appears instead of S[h] **/ 9908c2ecf20Sopenharmony_ci RFALSE(tb->blknum[h] > 2, "blknum can not be > 2 for internal level"); 9918c2ecf20Sopenharmony_ci RFALSE(tb->blknum[h] < 0, "blknum can not be < 0"); 9928c2ecf20Sopenharmony_ci 9938c2ecf20Sopenharmony_ci if (!tb->blknum[h]) { /* node S[h] is empty now */ 9948c2ecf20Sopenharmony_ci RFALSE(!tbSh, "S[h] is equal NULL"); 9958c2ecf20Sopenharmony_ci 9968c2ecf20Sopenharmony_ci /* do what is needed for buffer thrown from tree */ 9978c2ecf20Sopenharmony_ci reiserfs_invalidate_buffer(tb, tbSh); 9988c2ecf20Sopenharmony_ci return order; 9998c2ecf20Sopenharmony_ci } 10008c2ecf20Sopenharmony_ci 10018c2ecf20Sopenharmony_ci if (!tbSh) { 10028c2ecf20Sopenharmony_ci /* create new root */ 10038c2ecf20Sopenharmony_ci struct disk_child *dc; 10048c2ecf20Sopenharmony_ci struct buffer_head *tbSh_1 = PATH_H_PBUFFER(tb->tb_path, h - 1); 10058c2ecf20Sopenharmony_ci struct block_head *blkh; 10068c2ecf20Sopenharmony_ci 10078c2ecf20Sopenharmony_ci if (tb->blknum[h] != 1) 10088c2ecf20Sopenharmony_ci reiserfs_panic(NULL, "ibalance-3", "One new node " 10098c2ecf20Sopenharmony_ci "required for creating the new root"); 10108c2ecf20Sopenharmony_ci /* S[h] = empty buffer from the list FEB. */ 10118c2ecf20Sopenharmony_ci tbSh = get_FEB(tb); 10128c2ecf20Sopenharmony_ci blkh = B_BLK_HEAD(tbSh); 10138c2ecf20Sopenharmony_ci set_blkh_level(blkh, h + 1); 10148c2ecf20Sopenharmony_ci 10158c2ecf20Sopenharmony_ci /* Put the unique node-pointer to S[h] that points to S[h-1]. */ 10168c2ecf20Sopenharmony_ci 10178c2ecf20Sopenharmony_ci dc = B_N_CHILD(tbSh, 0); 10188c2ecf20Sopenharmony_ci put_dc_block_number(dc, tbSh_1->b_blocknr); 10198c2ecf20Sopenharmony_ci put_dc_size(dc, 10208c2ecf20Sopenharmony_ci (MAX_CHILD_SIZE(tbSh_1) - B_FREE_SPACE(tbSh_1))); 10218c2ecf20Sopenharmony_ci 10228c2ecf20Sopenharmony_ci tb->insert_size[h] -= DC_SIZE; 10238c2ecf20Sopenharmony_ci set_blkh_free_space(blkh, blkh_free_space(blkh) - DC_SIZE); 10248c2ecf20Sopenharmony_ci 10258c2ecf20Sopenharmony_ci do_balance_mark_internal_dirty(tb, tbSh, 0); 10268c2ecf20Sopenharmony_ci 10278c2ecf20Sopenharmony_ci /*&&&&&&&&&&&&&&&&&&&&&&&& */ 10288c2ecf20Sopenharmony_ci check_internal(tbSh); 10298c2ecf20Sopenharmony_ci /*&&&&&&&&&&&&&&&&&&&&&&&& */ 10308c2ecf20Sopenharmony_ci 10318c2ecf20Sopenharmony_ci /* put new root into path structure */ 10328c2ecf20Sopenharmony_ci PATH_OFFSET_PBUFFER(tb->tb_path, ILLEGAL_PATH_ELEMENT_OFFSET) = 10338c2ecf20Sopenharmony_ci tbSh; 10348c2ecf20Sopenharmony_ci 10358c2ecf20Sopenharmony_ci /* Change root in structure super block. */ 10368c2ecf20Sopenharmony_ci PUT_SB_ROOT_BLOCK(tb->tb_sb, tbSh->b_blocknr); 10378c2ecf20Sopenharmony_ci PUT_SB_TREE_HEIGHT(tb->tb_sb, SB_TREE_HEIGHT(tb->tb_sb) + 1); 10388c2ecf20Sopenharmony_ci do_balance_mark_sb_dirty(tb, REISERFS_SB(tb->tb_sb)->s_sbh, 1); 10398c2ecf20Sopenharmony_ci } 10408c2ecf20Sopenharmony_ci 10418c2ecf20Sopenharmony_ci if (tb->blknum[h] == 2) { 10428c2ecf20Sopenharmony_ci int snum; 10438c2ecf20Sopenharmony_ci struct buffer_info dest_bi, src_bi; 10448c2ecf20Sopenharmony_ci 10458c2ecf20Sopenharmony_ci /* S_new = free buffer from list FEB */ 10468c2ecf20Sopenharmony_ci S_new = get_FEB(tb); 10478c2ecf20Sopenharmony_ci 10488c2ecf20Sopenharmony_ci set_blkh_level(B_BLK_HEAD(S_new), h + 1); 10498c2ecf20Sopenharmony_ci 10508c2ecf20Sopenharmony_ci dest_bi.tb = tb; 10518c2ecf20Sopenharmony_ci dest_bi.bi_bh = S_new; 10528c2ecf20Sopenharmony_ci dest_bi.bi_parent = NULL; 10538c2ecf20Sopenharmony_ci dest_bi.bi_position = 0; 10548c2ecf20Sopenharmony_ci src_bi.tb = tb; 10558c2ecf20Sopenharmony_ci src_bi.bi_bh = tbSh; 10568c2ecf20Sopenharmony_ci src_bi.bi_parent = PATH_H_PPARENT(tb->tb_path, h); 10578c2ecf20Sopenharmony_ci src_bi.bi_position = PATH_H_POSITION(tb->tb_path, h + 1); 10588c2ecf20Sopenharmony_ci 10598c2ecf20Sopenharmony_ci n = B_NR_ITEMS(tbSh); /* number of items in S[h] */ 10608c2ecf20Sopenharmony_ci snum = (insert_num + n + 1) / 2; 10618c2ecf20Sopenharmony_ci if (n - snum >= child_pos) { 10628c2ecf20Sopenharmony_ci /* new items don't fall into S_new */ 10638c2ecf20Sopenharmony_ci /* store the delimiting key for the next level */ 10648c2ecf20Sopenharmony_ci /* new_insert_key = (n - snum)'th key in S[h] */ 10658c2ecf20Sopenharmony_ci memcpy(&new_insert_key, internal_key(tbSh, n - snum), 10668c2ecf20Sopenharmony_ci KEY_SIZE); 10678c2ecf20Sopenharmony_ci /* last parameter is del_par */ 10688c2ecf20Sopenharmony_ci internal_move_pointers_items(&dest_bi, &src_bi, 10698c2ecf20Sopenharmony_ci LAST_TO_FIRST, snum, 0); 10708c2ecf20Sopenharmony_ci } else if (n + insert_num - snum < child_pos) { 10718c2ecf20Sopenharmony_ci /* all new items fall into S_new */ 10728c2ecf20Sopenharmony_ci /* store the delimiting key for the next level */ 10738c2ecf20Sopenharmony_ci /* 10748c2ecf20Sopenharmony_ci * new_insert_key = (n + insert_item - snum)'th 10758c2ecf20Sopenharmony_ci * key in S[h] 10768c2ecf20Sopenharmony_ci */ 10778c2ecf20Sopenharmony_ci memcpy(&new_insert_key, 10788c2ecf20Sopenharmony_ci internal_key(tbSh, n + insert_num - snum), 10798c2ecf20Sopenharmony_ci KEY_SIZE); 10808c2ecf20Sopenharmony_ci /* last parameter is del_par */ 10818c2ecf20Sopenharmony_ci internal_move_pointers_items(&dest_bi, &src_bi, 10828c2ecf20Sopenharmony_ci LAST_TO_FIRST, 10838c2ecf20Sopenharmony_ci snum - insert_num, 0); 10848c2ecf20Sopenharmony_ci 10858c2ecf20Sopenharmony_ci /* 10868c2ecf20Sopenharmony_ci * insert insert_num keys and node-pointers 10878c2ecf20Sopenharmony_ci * into S_new 10888c2ecf20Sopenharmony_ci */ 10898c2ecf20Sopenharmony_ci internal_insert_childs(&dest_bi, 10908c2ecf20Sopenharmony_ci /*S_new,tb->S[h-1]->b_next, */ 10918c2ecf20Sopenharmony_ci child_pos - n - insert_num + 10928c2ecf20Sopenharmony_ci snum - 1, 10938c2ecf20Sopenharmony_ci insert_num, insert_key, 10948c2ecf20Sopenharmony_ci insert_ptr); 10958c2ecf20Sopenharmony_ci 10968c2ecf20Sopenharmony_ci insert_num = 0; 10978c2ecf20Sopenharmony_ci } else { 10988c2ecf20Sopenharmony_ci struct disk_child *dc; 10998c2ecf20Sopenharmony_ci 11008c2ecf20Sopenharmony_ci /* some items fall into S_new, but some don't fall */ 11018c2ecf20Sopenharmony_ci /* last parameter is del_par */ 11028c2ecf20Sopenharmony_ci internal_move_pointers_items(&dest_bi, &src_bi, 11038c2ecf20Sopenharmony_ci LAST_TO_FIRST, 11048c2ecf20Sopenharmony_ci n - child_pos + 1, 1); 11058c2ecf20Sopenharmony_ci /* calculate number of new items that fall into S_new */ 11068c2ecf20Sopenharmony_ci k = snum - n + child_pos - 1; 11078c2ecf20Sopenharmony_ci 11088c2ecf20Sopenharmony_ci internal_insert_childs(&dest_bi, /*S_new, */ 0, k, 11098c2ecf20Sopenharmony_ci insert_key + 1, insert_ptr + 1); 11108c2ecf20Sopenharmony_ci 11118c2ecf20Sopenharmony_ci /* new_insert_key = insert_key[insert_num - k - 1] */ 11128c2ecf20Sopenharmony_ci memcpy(&new_insert_key, insert_key + insert_num - k - 1, 11138c2ecf20Sopenharmony_ci KEY_SIZE); 11148c2ecf20Sopenharmony_ci /* 11158c2ecf20Sopenharmony_ci * replace first node-ptr in S_new by node-ptr 11168c2ecf20Sopenharmony_ci * to insert_ptr[insert_num-k-1] 11178c2ecf20Sopenharmony_ci */ 11188c2ecf20Sopenharmony_ci 11198c2ecf20Sopenharmony_ci dc = B_N_CHILD(S_new, 0); 11208c2ecf20Sopenharmony_ci put_dc_size(dc, 11218c2ecf20Sopenharmony_ci (MAX_CHILD_SIZE 11228c2ecf20Sopenharmony_ci (insert_ptr[insert_num - k - 1]) - 11238c2ecf20Sopenharmony_ci B_FREE_SPACE(insert_ptr 11248c2ecf20Sopenharmony_ci [insert_num - k - 1]))); 11258c2ecf20Sopenharmony_ci put_dc_block_number(dc, 11268c2ecf20Sopenharmony_ci insert_ptr[insert_num - k - 11278c2ecf20Sopenharmony_ci 1]->b_blocknr); 11288c2ecf20Sopenharmony_ci 11298c2ecf20Sopenharmony_ci do_balance_mark_internal_dirty(tb, S_new, 0); 11308c2ecf20Sopenharmony_ci 11318c2ecf20Sopenharmony_ci insert_num -= (k + 1); 11328c2ecf20Sopenharmony_ci } 11338c2ecf20Sopenharmony_ci /* new_insert_ptr = node_pointer to S_new */ 11348c2ecf20Sopenharmony_ci new_insert_ptr = S_new; 11358c2ecf20Sopenharmony_ci 11368c2ecf20Sopenharmony_ci RFALSE(!buffer_journaled(S_new) || buffer_journal_dirty(S_new) 11378c2ecf20Sopenharmony_ci || buffer_dirty(S_new), "cm-00001: bad S_new (%b)", 11388c2ecf20Sopenharmony_ci S_new); 11398c2ecf20Sopenharmony_ci 11408c2ecf20Sopenharmony_ci /* S_new is released in unfix_nodes */ 11418c2ecf20Sopenharmony_ci } 11428c2ecf20Sopenharmony_ci 11438c2ecf20Sopenharmony_ci n = B_NR_ITEMS(tbSh); /*number of items in S[h] */ 11448c2ecf20Sopenharmony_ci 11458c2ecf20Sopenharmony_ci if (0 <= child_pos && child_pos <= n && insert_num > 0) { 11468c2ecf20Sopenharmony_ci bi.tb = tb; 11478c2ecf20Sopenharmony_ci bi.bi_bh = tbSh; 11488c2ecf20Sopenharmony_ci bi.bi_parent = PATH_H_PPARENT(tb->tb_path, h); 11498c2ecf20Sopenharmony_ci bi.bi_position = PATH_H_POSITION(tb->tb_path, h + 1); 11508c2ecf20Sopenharmony_ci internal_insert_childs(&bi, /*tbSh, */ 11518c2ecf20Sopenharmony_ci /* ( tb->S[h-1]->b_parent == tb->S[h] ) ? tb->S[h-1]->b_next : tb->S[h]->b_child->b_next, */ 11528c2ecf20Sopenharmony_ci child_pos, insert_num, insert_key, 11538c2ecf20Sopenharmony_ci insert_ptr); 11548c2ecf20Sopenharmony_ci } 11558c2ecf20Sopenharmony_ci 11568c2ecf20Sopenharmony_ci insert_ptr[0] = new_insert_ptr; 11578c2ecf20Sopenharmony_ci if (new_insert_ptr) 11588c2ecf20Sopenharmony_ci memcpy(new_insert_key_addr, &new_insert_key, KEY_SIZE); 11598c2ecf20Sopenharmony_ci 11608c2ecf20Sopenharmony_ci return order; 11618c2ecf20Sopenharmony_ci} 1162