11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README 31da177e4SLinus Torvalds */ 41da177e4SLinus Torvalds 51da177e4SLinus Torvalds #include <asm/uaccess.h> 61da177e4SLinus Torvalds #include <linux/string.h> 71da177e4SLinus Torvalds #include <linux/time.h> 8f466c6fdSAl Viro #include "reiserfs.h" 91da177e4SLinus Torvalds #include <linux/buffer_head.h> 101da177e4SLinus Torvalds 111da177e4SLinus Torvalds /* this is one and only function that is used outside (do_balance.c) */ 12bd4c625cSLinus Torvalds int balance_internal(struct tree_balance *, 13bd4c625cSLinus Torvalds int, int, struct item_head *, struct buffer_head **); 141da177e4SLinus Torvalds 151da177e4SLinus Torvalds /* modes of internal_shift_left, internal_shift_right and internal_insert_childs */ 161da177e4SLinus Torvalds #define INTERNAL_SHIFT_FROM_S_TO_L 0 171da177e4SLinus Torvalds #define INTERNAL_SHIFT_FROM_R_TO_S 1 181da177e4SLinus Torvalds #define INTERNAL_SHIFT_FROM_L_TO_S 2 191da177e4SLinus Torvalds #define INTERNAL_SHIFT_FROM_S_TO_R 3 201da177e4SLinus Torvalds #define INTERNAL_INSERT_TO_S 4 211da177e4SLinus Torvalds #define INTERNAL_INSERT_TO_L 5 221da177e4SLinus Torvalds #define INTERNAL_INSERT_TO_R 6 231da177e4SLinus Torvalds 24bd4c625cSLinus Torvalds static void internal_define_dest_src_infos(int shift_mode, 251da177e4SLinus Torvalds struct tree_balance *tb, 261da177e4SLinus Torvalds int h, 271da177e4SLinus Torvalds struct buffer_info *dest_bi, 281da177e4SLinus Torvalds struct buffer_info *src_bi, 29bd4c625cSLinus Torvalds int *d_key, struct buffer_head **cf) 301da177e4SLinus Torvalds { 311da177e4SLinus Torvalds memset(dest_bi, 0, sizeof(struct buffer_info)); 321da177e4SLinus Torvalds memset(src_bi, 0, sizeof(struct buffer_info)); 331da177e4SLinus Torvalds /* define dest, src, dest parent, dest position */ 341da177e4SLinus Torvalds switch (shift_mode) { 351da177e4SLinus Torvalds case INTERNAL_SHIFT_FROM_S_TO_L: /* used in internal_shift_left */ 361da177e4SLinus Torvalds src_bi->tb = tb; 371da177e4SLinus Torvalds src_bi->bi_bh = PATH_H_PBUFFER(tb->tb_path, h); 381da177e4SLinus Torvalds src_bi->bi_parent = PATH_H_PPARENT(tb->tb_path, h); 391da177e4SLinus Torvalds src_bi->bi_position = PATH_H_POSITION(tb->tb_path, h + 1); 401da177e4SLinus Torvalds dest_bi->tb = tb; 411da177e4SLinus Torvalds dest_bi->bi_bh = tb->L[h]; 421da177e4SLinus Torvalds dest_bi->bi_parent = tb->FL[h]; 431da177e4SLinus Torvalds dest_bi->bi_position = get_left_neighbor_position(tb, h); 441da177e4SLinus Torvalds *d_key = tb->lkey[h]; 451da177e4SLinus Torvalds *cf = tb->CFL[h]; 461da177e4SLinus Torvalds break; 471da177e4SLinus Torvalds case INTERNAL_SHIFT_FROM_L_TO_S: 481da177e4SLinus Torvalds src_bi->tb = tb; 491da177e4SLinus Torvalds src_bi->bi_bh = tb->L[h]; 501da177e4SLinus Torvalds src_bi->bi_parent = tb->FL[h]; 511da177e4SLinus Torvalds src_bi->bi_position = get_left_neighbor_position(tb, h); 521da177e4SLinus Torvalds dest_bi->tb = tb; 531da177e4SLinus Torvalds dest_bi->bi_bh = PATH_H_PBUFFER(tb->tb_path, h); 541da177e4SLinus Torvalds dest_bi->bi_parent = PATH_H_PPARENT(tb->tb_path, h); 551da177e4SLinus Torvalds dest_bi->bi_position = PATH_H_POSITION(tb->tb_path, h + 1); /* dest position is analog of dest->b_item_order */ 561da177e4SLinus Torvalds *d_key = tb->lkey[h]; 571da177e4SLinus Torvalds *cf = tb->CFL[h]; 581da177e4SLinus Torvalds break; 591da177e4SLinus Torvalds 601da177e4SLinus Torvalds case INTERNAL_SHIFT_FROM_R_TO_S: /* used in internal_shift_left */ 611da177e4SLinus Torvalds src_bi->tb = tb; 621da177e4SLinus Torvalds src_bi->bi_bh = tb->R[h]; 631da177e4SLinus Torvalds src_bi->bi_parent = tb->FR[h]; 641da177e4SLinus Torvalds src_bi->bi_position = get_right_neighbor_position(tb, h); 651da177e4SLinus Torvalds dest_bi->tb = tb; 661da177e4SLinus Torvalds dest_bi->bi_bh = PATH_H_PBUFFER(tb->tb_path, h); 671da177e4SLinus Torvalds dest_bi->bi_parent = PATH_H_PPARENT(tb->tb_path, h); 681da177e4SLinus Torvalds dest_bi->bi_position = PATH_H_POSITION(tb->tb_path, h + 1); 691da177e4SLinus Torvalds *d_key = tb->rkey[h]; 701da177e4SLinus Torvalds *cf = tb->CFR[h]; 711da177e4SLinus Torvalds break; 721da177e4SLinus Torvalds 731da177e4SLinus Torvalds case INTERNAL_SHIFT_FROM_S_TO_R: 741da177e4SLinus Torvalds src_bi->tb = tb; 751da177e4SLinus Torvalds src_bi->bi_bh = PATH_H_PBUFFER(tb->tb_path, h); 761da177e4SLinus Torvalds src_bi->bi_parent = PATH_H_PPARENT(tb->tb_path, h); 771da177e4SLinus Torvalds src_bi->bi_position = PATH_H_POSITION(tb->tb_path, h + 1); 781da177e4SLinus Torvalds dest_bi->tb = tb; 791da177e4SLinus Torvalds dest_bi->bi_bh = tb->R[h]; 801da177e4SLinus Torvalds dest_bi->bi_parent = tb->FR[h]; 811da177e4SLinus Torvalds dest_bi->bi_position = get_right_neighbor_position(tb, h); 821da177e4SLinus Torvalds *d_key = tb->rkey[h]; 831da177e4SLinus Torvalds *cf = tb->CFR[h]; 841da177e4SLinus Torvalds break; 851da177e4SLinus Torvalds 861da177e4SLinus Torvalds case INTERNAL_INSERT_TO_L: 871da177e4SLinus Torvalds dest_bi->tb = tb; 881da177e4SLinus Torvalds dest_bi->bi_bh = tb->L[h]; 891da177e4SLinus Torvalds dest_bi->bi_parent = tb->FL[h]; 901da177e4SLinus Torvalds dest_bi->bi_position = get_left_neighbor_position(tb, h); 911da177e4SLinus Torvalds break; 921da177e4SLinus Torvalds 931da177e4SLinus Torvalds case INTERNAL_INSERT_TO_S: 941da177e4SLinus Torvalds dest_bi->tb = tb; 951da177e4SLinus Torvalds dest_bi->bi_bh = PATH_H_PBUFFER(tb->tb_path, h); 961da177e4SLinus Torvalds dest_bi->bi_parent = PATH_H_PPARENT(tb->tb_path, h); 971da177e4SLinus Torvalds dest_bi->bi_position = PATH_H_POSITION(tb->tb_path, h + 1); 981da177e4SLinus Torvalds break; 991da177e4SLinus Torvalds 1001da177e4SLinus Torvalds case INTERNAL_INSERT_TO_R: 1011da177e4SLinus Torvalds dest_bi->tb = tb; 1021da177e4SLinus Torvalds dest_bi->bi_bh = tb->R[h]; 1031da177e4SLinus Torvalds dest_bi->bi_parent = tb->FR[h]; 1041da177e4SLinus Torvalds dest_bi->bi_position = get_right_neighbor_position(tb, h); 1051da177e4SLinus Torvalds break; 1061da177e4SLinus Torvalds 1071da177e4SLinus Torvalds default: 108c3a9c210SJeff Mahoney reiserfs_panic(tb->tb_sb, "ibalance-1", 109c3a9c210SJeff Mahoney "shift type is unknown (%d)", 110bd4c625cSLinus Torvalds shift_mode); 1111da177e4SLinus Torvalds } 1121da177e4SLinus Torvalds } 1131da177e4SLinus Torvalds 1141da177e4SLinus Torvalds /* Insert count node pointers into buffer cur before position to + 1. 1151da177e4SLinus Torvalds * Insert count items into buffer cur before position to. 1161da177e4SLinus Torvalds * Items and node pointers are specified by inserted and bh respectively. 1171da177e4SLinus Torvalds */ 1181da177e4SLinus Torvalds static void internal_insert_childs(struct buffer_info *cur_bi, 1191da177e4SLinus Torvalds int to, int count, 1201da177e4SLinus Torvalds struct item_head *inserted, 121bd4c625cSLinus Torvalds struct buffer_head **bh) 1221da177e4SLinus Torvalds { 1231da177e4SLinus Torvalds struct buffer_head *cur = cur_bi->bi_bh; 1241da177e4SLinus Torvalds struct block_head *blkh; 1251da177e4SLinus Torvalds int nr; 1261da177e4SLinus Torvalds struct reiserfs_key *ih; 1271da177e4SLinus Torvalds struct disk_child new_dc[2]; 1281da177e4SLinus Torvalds struct disk_child *dc; 1291da177e4SLinus Torvalds int i; 1301da177e4SLinus Torvalds 1311da177e4SLinus Torvalds if (count <= 0) 1321da177e4SLinus Torvalds return; 1331da177e4SLinus Torvalds 1341da177e4SLinus Torvalds blkh = B_BLK_HEAD(cur); 1351da177e4SLinus Torvalds nr = blkh_nr_item(blkh); 1361da177e4SLinus Torvalds 137bd4c625cSLinus Torvalds RFALSE(count > 2, "too many children (%d) are to be inserted", count); 1381da177e4SLinus Torvalds RFALSE(B_FREE_SPACE(cur) < count * (KEY_SIZE + DC_SIZE), 1391da177e4SLinus Torvalds "no enough free space (%d), needed %d bytes", 1401da177e4SLinus Torvalds B_FREE_SPACE(cur), count * (KEY_SIZE + DC_SIZE)); 1411da177e4SLinus Torvalds 1421da177e4SLinus Torvalds /* prepare space for count disk_child */ 1431da177e4SLinus Torvalds dc = B_N_CHILD(cur, to + 1); 1441da177e4SLinus Torvalds 1451da177e4SLinus Torvalds memmove(dc + count, dc, (nr + 1 - (to + 1)) * DC_SIZE); 1461da177e4SLinus Torvalds 1471da177e4SLinus Torvalds /* copy to_be_insert disk children */ 1481da177e4SLinus Torvalds for (i = 0; i < count; i++) { 149bd4c625cSLinus Torvalds put_dc_size(&(new_dc[i]), 150bd4c625cSLinus Torvalds MAX_CHILD_SIZE(bh[i]) - B_FREE_SPACE(bh[i])); 1511da177e4SLinus Torvalds put_dc_block_number(&(new_dc[i]), bh[i]->b_blocknr); 1521da177e4SLinus Torvalds } 1531da177e4SLinus Torvalds memcpy(dc, new_dc, DC_SIZE * count); 1541da177e4SLinus Torvalds 1551da177e4SLinus Torvalds /* prepare space for count items */ 1564cf5f7adSJeff Mahoney ih = internal_key(cur, ((to == -1) ? 0 : to)); 1571da177e4SLinus Torvalds 158bd4c625cSLinus Torvalds memmove(ih + count, ih, 159bd4c625cSLinus Torvalds (nr - to) * KEY_SIZE + (nr + 1 + count) * DC_SIZE); 1601da177e4SLinus Torvalds 1611da177e4SLinus Torvalds /* copy item headers (keys) */ 1621da177e4SLinus Torvalds memcpy(ih, inserted, KEY_SIZE); 1631da177e4SLinus Torvalds if (count > 1) 1641da177e4SLinus Torvalds memcpy(ih + 1, inserted + 1, KEY_SIZE); 1651da177e4SLinus Torvalds 1661da177e4SLinus Torvalds /* sizes, item number */ 1671da177e4SLinus Torvalds set_blkh_nr_item(blkh, blkh_nr_item(blkh) + count); 1681da177e4SLinus Torvalds set_blkh_free_space(blkh, 169bd4c625cSLinus Torvalds blkh_free_space(blkh) - count * (DC_SIZE + 170bd4c625cSLinus Torvalds KEY_SIZE)); 1711da177e4SLinus Torvalds 1721da177e4SLinus Torvalds do_balance_mark_internal_dirty(cur_bi->tb, cur, 0); 1731da177e4SLinus Torvalds 1741da177e4SLinus Torvalds /*&&&&&&&&&&&&&&&&&&&&&&&& */ 1751da177e4SLinus Torvalds check_internal(cur); 1761da177e4SLinus Torvalds /*&&&&&&&&&&&&&&&&&&&&&&&& */ 1771da177e4SLinus Torvalds 1781da177e4SLinus Torvalds if (cur_bi->bi_parent) { 179bd4c625cSLinus Torvalds struct disk_child *t_dc = 180bd4c625cSLinus Torvalds B_N_CHILD(cur_bi->bi_parent, cur_bi->bi_position); 181bd4c625cSLinus Torvalds put_dc_size(t_dc, 182bd4c625cSLinus Torvalds dc_size(t_dc) + (count * (DC_SIZE + KEY_SIZE))); 183bd4c625cSLinus Torvalds do_balance_mark_internal_dirty(cur_bi->tb, cur_bi->bi_parent, 184bd4c625cSLinus Torvalds 0); 1851da177e4SLinus Torvalds 1861da177e4SLinus Torvalds /*&&&&&&&&&&&&&&&&&&&&&&&& */ 1871da177e4SLinus Torvalds check_internal(cur_bi->bi_parent); 1881da177e4SLinus Torvalds /*&&&&&&&&&&&&&&&&&&&&&&&& */ 1891da177e4SLinus Torvalds } 1901da177e4SLinus Torvalds 1911da177e4SLinus Torvalds } 1921da177e4SLinus Torvalds 1931da177e4SLinus Torvalds /* Delete del_num items and node pointers from buffer cur starting from * 1941da177e4SLinus Torvalds * the first_i'th item and first_p'th pointers respectively. */ 195bd4c625cSLinus Torvalds static void internal_delete_pointers_items(struct buffer_info *cur_bi, 1961da177e4SLinus Torvalds int first_p, 197bd4c625cSLinus Torvalds int first_i, int del_num) 1981da177e4SLinus Torvalds { 1991da177e4SLinus Torvalds struct buffer_head *cur = cur_bi->bi_bh; 2001da177e4SLinus Torvalds int nr; 2011da177e4SLinus Torvalds struct block_head *blkh; 2021da177e4SLinus Torvalds struct reiserfs_key *key; 2031da177e4SLinus Torvalds struct disk_child *dc; 2041da177e4SLinus Torvalds 2051da177e4SLinus Torvalds RFALSE(cur == NULL, "buffer is 0"); 2061da177e4SLinus Torvalds RFALSE(del_num < 0, 2071da177e4SLinus Torvalds "negative number of items (%d) can not be deleted", del_num); 208bd4c625cSLinus Torvalds RFALSE(first_p < 0 || first_p + del_num > B_NR_ITEMS(cur) + 1 209bd4c625cSLinus Torvalds || first_i < 0, 2101da177e4SLinus Torvalds "first pointer order (%d) < 0 or " 2111da177e4SLinus Torvalds "no so many pointers (%d), only (%d) or " 212bd4c625cSLinus Torvalds "first key order %d < 0", first_p, first_p + del_num, 213bd4c625cSLinus Torvalds B_NR_ITEMS(cur) + 1, first_i); 2141da177e4SLinus Torvalds if (del_num == 0) 2151da177e4SLinus Torvalds return; 2161da177e4SLinus Torvalds 2171da177e4SLinus Torvalds blkh = B_BLK_HEAD(cur); 2181da177e4SLinus Torvalds nr = blkh_nr_item(blkh); 2191da177e4SLinus Torvalds 2201da177e4SLinus Torvalds if (first_p == 0 && del_num == nr + 1) { 221bd4c625cSLinus Torvalds RFALSE(first_i != 0, 222bd4c625cSLinus Torvalds "1st deleted key must have order 0, not %d", first_i); 2231da177e4SLinus Torvalds make_empty_node(cur_bi); 2241da177e4SLinus Torvalds return; 2251da177e4SLinus Torvalds } 2261da177e4SLinus Torvalds 2271da177e4SLinus Torvalds RFALSE(first_i + del_num > B_NR_ITEMS(cur), 2281da177e4SLinus Torvalds "first_i = %d del_num = %d " 2291da177e4SLinus Torvalds "no so many keys (%d) in the node (%b)(%z)", 2301da177e4SLinus Torvalds first_i, del_num, first_i + del_num, cur, cur); 2311da177e4SLinus Torvalds 2321da177e4SLinus Torvalds /* deleting */ 2331da177e4SLinus Torvalds dc = B_N_CHILD(cur, first_p); 2341da177e4SLinus Torvalds 2351da177e4SLinus Torvalds memmove(dc, dc + del_num, (nr + 1 - first_p - del_num) * DC_SIZE); 2364cf5f7adSJeff Mahoney key = internal_key(cur, first_i); 237bd4c625cSLinus Torvalds memmove(key, key + del_num, 238bd4c625cSLinus Torvalds (nr - first_i - del_num) * KEY_SIZE + (nr + 1 - 239bd4c625cSLinus Torvalds del_num) * DC_SIZE); 2401da177e4SLinus Torvalds 2411da177e4SLinus Torvalds /* sizes, item number */ 2421da177e4SLinus Torvalds set_blkh_nr_item(blkh, blkh_nr_item(blkh) - del_num); 2431da177e4SLinus Torvalds set_blkh_free_space(blkh, 244bd4c625cSLinus Torvalds blkh_free_space(blkh) + 245bd4c625cSLinus Torvalds (del_num * (KEY_SIZE + DC_SIZE))); 2461da177e4SLinus Torvalds 2471da177e4SLinus Torvalds do_balance_mark_internal_dirty(cur_bi->tb, cur, 0); 2481da177e4SLinus Torvalds /*&&&&&&&&&&&&&&&&&&&&&&& */ 2491da177e4SLinus Torvalds check_internal(cur); 2501da177e4SLinus Torvalds /*&&&&&&&&&&&&&&&&&&&&&&& */ 2511da177e4SLinus Torvalds 2521da177e4SLinus Torvalds if (cur_bi->bi_parent) { 2531da177e4SLinus Torvalds struct disk_child *t_dc; 2541da177e4SLinus Torvalds t_dc = B_N_CHILD(cur_bi->bi_parent, cur_bi->bi_position); 255bd4c625cSLinus Torvalds put_dc_size(t_dc, 256bd4c625cSLinus Torvalds dc_size(t_dc) - (del_num * (KEY_SIZE + DC_SIZE))); 2571da177e4SLinus Torvalds 258bd4c625cSLinus Torvalds do_balance_mark_internal_dirty(cur_bi->tb, cur_bi->bi_parent, 259bd4c625cSLinus Torvalds 0); 2601da177e4SLinus Torvalds /*&&&&&&&&&&&&&&&&&&&&&&&& */ 2611da177e4SLinus Torvalds check_internal(cur_bi->bi_parent); 2621da177e4SLinus Torvalds /*&&&&&&&&&&&&&&&&&&&&&&&& */ 2631da177e4SLinus Torvalds } 2641da177e4SLinus Torvalds } 2651da177e4SLinus Torvalds 2661da177e4SLinus Torvalds /* delete n node pointers and items starting from given position */ 267bd4c625cSLinus Torvalds static void internal_delete_childs(struct buffer_info *cur_bi, int from, int n) 2681da177e4SLinus Torvalds { 2691da177e4SLinus Torvalds int i_from; 2701da177e4SLinus Torvalds 2711da177e4SLinus Torvalds i_from = (from == 0) ? from : from - 1; 2721da177e4SLinus Torvalds 2731da177e4SLinus Torvalds /* delete n pointers starting from `from' position in CUR; 2741da177e4SLinus Torvalds delete n keys starting from 'i_from' position in CUR; 2751da177e4SLinus Torvalds */ 2761da177e4SLinus Torvalds internal_delete_pointers_items(cur_bi, from, i_from, n); 2771da177e4SLinus Torvalds } 2781da177e4SLinus Torvalds 2791da177e4SLinus Torvalds /* copy cpy_num node pointers and cpy_num - 1 items from buffer src to buffer dest 2801da177e4SLinus Torvalds * last_first == FIRST_TO_LAST means, that we copy first items from src to tail of dest 2811da177e4SLinus Torvalds * last_first == LAST_TO_FIRST means, that we copy last items from src to head of dest 2821da177e4SLinus Torvalds */ 283bd4c625cSLinus Torvalds static void internal_copy_pointers_items(struct buffer_info *dest_bi, 2841da177e4SLinus Torvalds struct buffer_head *src, 285bd4c625cSLinus Torvalds int last_first, int cpy_num) 2861da177e4SLinus Torvalds { 2871da177e4SLinus Torvalds /* ATTENTION! Number of node pointers in DEST is equal to number of items in DEST * 2881da177e4SLinus Torvalds * as delimiting key have already inserted to buffer dest.*/ 2891da177e4SLinus Torvalds struct buffer_head *dest = dest_bi->bi_bh; 2901da177e4SLinus Torvalds int nr_dest, nr_src; 2911da177e4SLinus Torvalds int dest_order, src_order; 2921da177e4SLinus Torvalds struct block_head *blkh; 2931da177e4SLinus Torvalds struct reiserfs_key *key; 2941da177e4SLinus Torvalds struct disk_child *dc; 2951da177e4SLinus Torvalds 2961da177e4SLinus Torvalds nr_src = B_NR_ITEMS(src); 2971da177e4SLinus Torvalds 2981da177e4SLinus Torvalds RFALSE(dest == NULL || src == NULL, 2991da177e4SLinus Torvalds "src (%p) or dest (%p) buffer is 0", src, dest); 3001da177e4SLinus Torvalds RFALSE(last_first != FIRST_TO_LAST && last_first != LAST_TO_FIRST, 3011da177e4SLinus Torvalds "invalid last_first parameter (%d)", last_first); 3021da177e4SLinus Torvalds RFALSE(nr_src < cpy_num - 1, 3031da177e4SLinus Torvalds "no so many items (%d) in src (%d)", cpy_num, nr_src); 3041da177e4SLinus Torvalds RFALSE(cpy_num < 0, "cpy_num less than 0 (%d)", cpy_num); 3051da177e4SLinus Torvalds RFALSE(cpy_num - 1 + B_NR_ITEMS(dest) > (int)MAX_NR_KEY(dest), 3061da177e4SLinus Torvalds "cpy_num (%d) + item number in dest (%d) can not be > MAX_NR_KEY(%d)", 3071da177e4SLinus Torvalds cpy_num, B_NR_ITEMS(dest), MAX_NR_KEY(dest)); 3081da177e4SLinus Torvalds 3091da177e4SLinus Torvalds if (cpy_num == 0) 3101da177e4SLinus Torvalds return; 3111da177e4SLinus Torvalds 3121da177e4SLinus Torvalds /* coping */ 3131da177e4SLinus Torvalds blkh = B_BLK_HEAD(dest); 3141da177e4SLinus Torvalds nr_dest = blkh_nr_item(blkh); 3151da177e4SLinus Torvalds 3161da177e4SLinus Torvalds /*dest_order = (last_first == LAST_TO_FIRST) ? 0 : nr_dest; */ 3171da177e4SLinus Torvalds /*src_order = (last_first == LAST_TO_FIRST) ? (nr_src - cpy_num + 1) : 0; */ 318bd4c625cSLinus Torvalds (last_first == LAST_TO_FIRST) ? (dest_order = 0, src_order = 319bd4c625cSLinus Torvalds nr_src - cpy_num + 1) : (dest_order = 320bd4c625cSLinus Torvalds nr_dest, 321bd4c625cSLinus Torvalds src_order = 322bd4c625cSLinus Torvalds 0); 3231da177e4SLinus Torvalds 3241da177e4SLinus Torvalds /* prepare space for cpy_num pointers */ 3251da177e4SLinus Torvalds dc = B_N_CHILD(dest, dest_order); 3261da177e4SLinus Torvalds 3271da177e4SLinus Torvalds memmove(dc + cpy_num, dc, (nr_dest - dest_order) * DC_SIZE); 3281da177e4SLinus Torvalds 3291da177e4SLinus Torvalds /* insert pointers */ 3301da177e4SLinus Torvalds memcpy(dc, B_N_CHILD(src, src_order), DC_SIZE * cpy_num); 3311da177e4SLinus Torvalds 3321da177e4SLinus Torvalds /* prepare space for cpy_num - 1 item headers */ 3334cf5f7adSJeff Mahoney key = internal_key(dest, dest_order); 3341da177e4SLinus Torvalds memmove(key + cpy_num - 1, key, 335bd4c625cSLinus Torvalds KEY_SIZE * (nr_dest - dest_order) + DC_SIZE * (nr_dest + 336bd4c625cSLinus Torvalds cpy_num)); 3371da177e4SLinus Torvalds 3381da177e4SLinus Torvalds /* insert headers */ 3394cf5f7adSJeff Mahoney memcpy(key, internal_key(src, src_order), KEY_SIZE * (cpy_num - 1)); 3401da177e4SLinus Torvalds 3411da177e4SLinus Torvalds /* sizes, item number */ 3421da177e4SLinus Torvalds set_blkh_nr_item(blkh, blkh_nr_item(blkh) + (cpy_num - 1)); 3431da177e4SLinus Torvalds set_blkh_free_space(blkh, 344bd4c625cSLinus Torvalds blkh_free_space(blkh) - (KEY_SIZE * (cpy_num - 1) + 345bd4c625cSLinus Torvalds DC_SIZE * cpy_num)); 3461da177e4SLinus Torvalds 3471da177e4SLinus Torvalds do_balance_mark_internal_dirty(dest_bi->tb, dest, 0); 3481da177e4SLinus Torvalds 3491da177e4SLinus Torvalds /*&&&&&&&&&&&&&&&&&&&&&&&& */ 3501da177e4SLinus Torvalds check_internal(dest); 3511da177e4SLinus Torvalds /*&&&&&&&&&&&&&&&&&&&&&&&& */ 3521da177e4SLinus Torvalds 3531da177e4SLinus Torvalds if (dest_bi->bi_parent) { 3541da177e4SLinus Torvalds struct disk_child *t_dc; 3551da177e4SLinus Torvalds t_dc = B_N_CHILD(dest_bi->bi_parent, dest_bi->bi_position); 356bd4c625cSLinus Torvalds put_dc_size(t_dc, 357bd4c625cSLinus Torvalds dc_size(t_dc) + (KEY_SIZE * (cpy_num - 1) + 358bd4c625cSLinus Torvalds DC_SIZE * cpy_num)); 3591da177e4SLinus Torvalds 360bd4c625cSLinus Torvalds do_balance_mark_internal_dirty(dest_bi->tb, dest_bi->bi_parent, 361bd4c625cSLinus Torvalds 0); 3621da177e4SLinus Torvalds /*&&&&&&&&&&&&&&&&&&&&&&&& */ 3631da177e4SLinus Torvalds check_internal(dest_bi->bi_parent); 3641da177e4SLinus Torvalds /*&&&&&&&&&&&&&&&&&&&&&&&& */ 3651da177e4SLinus Torvalds } 3661da177e4SLinus Torvalds 3671da177e4SLinus Torvalds } 3681da177e4SLinus Torvalds 3691da177e4SLinus Torvalds /* Copy cpy_num node pointers and cpy_num - 1 items from buffer src to buffer dest. 3701da177e4SLinus Torvalds * Delete cpy_num - del_par items and node pointers from buffer src. 3711da177e4SLinus Torvalds * last_first == FIRST_TO_LAST means, that we copy/delete first items from src. 3721da177e4SLinus Torvalds * last_first == LAST_TO_FIRST means, that we copy/delete last items from src. 3731da177e4SLinus Torvalds */ 3741da177e4SLinus Torvalds static void internal_move_pointers_items(struct buffer_info *dest_bi, 3751da177e4SLinus Torvalds struct buffer_info *src_bi, 376bd4c625cSLinus Torvalds int last_first, int cpy_num, 377bd4c625cSLinus Torvalds int del_par) 3781da177e4SLinus Torvalds { 3791da177e4SLinus Torvalds int first_pointer; 3801da177e4SLinus Torvalds int first_item; 3811da177e4SLinus Torvalds 382bd4c625cSLinus Torvalds internal_copy_pointers_items(dest_bi, src_bi->bi_bh, last_first, 383bd4c625cSLinus Torvalds cpy_num); 3841da177e4SLinus Torvalds 3851da177e4SLinus Torvalds if (last_first == FIRST_TO_LAST) { /* shift_left occurs */ 3861da177e4SLinus Torvalds first_pointer = 0; 3871da177e4SLinus Torvalds first_item = 0; 3881da177e4SLinus Torvalds /* delete cpy_num - del_par pointers and keys starting for pointers with first_pointer, 3891da177e4SLinus Torvalds for key - with first_item */ 390bd4c625cSLinus Torvalds internal_delete_pointers_items(src_bi, first_pointer, 391bd4c625cSLinus Torvalds first_item, cpy_num - del_par); 3921da177e4SLinus Torvalds } else { /* shift_right occurs */ 3931da177e4SLinus Torvalds int i, j; 3941da177e4SLinus Torvalds 395bd4c625cSLinus Torvalds i = (cpy_num - del_par == 396bd4c625cSLinus Torvalds (j = 397bd4c625cSLinus Torvalds B_NR_ITEMS(src_bi->bi_bh)) + 1) ? 0 : j - cpy_num + 398bd4c625cSLinus Torvalds del_par; 3991da177e4SLinus Torvalds 400bd4c625cSLinus Torvalds internal_delete_pointers_items(src_bi, 401bd4c625cSLinus Torvalds j + 1 - cpy_num + del_par, i, 402bd4c625cSLinus Torvalds cpy_num - del_par); 4031da177e4SLinus Torvalds } 4041da177e4SLinus Torvalds } 4051da177e4SLinus Torvalds 4061da177e4SLinus Torvalds /* Insert n_src'th key of buffer src before n_dest'th key of buffer dest. */ 407bd4c625cSLinus Torvalds static void internal_insert_key(struct buffer_info *dest_bi, int dest_position_before, /* insert key before key with n_dest number */ 408bd4c625cSLinus Torvalds struct buffer_head *src, int src_position) 4091da177e4SLinus Torvalds { 4101da177e4SLinus Torvalds struct buffer_head *dest = dest_bi->bi_bh; 4111da177e4SLinus Torvalds int nr; 4121da177e4SLinus Torvalds struct block_head *blkh; 4131da177e4SLinus Torvalds struct reiserfs_key *key; 4141da177e4SLinus Torvalds 4151da177e4SLinus Torvalds RFALSE(dest == NULL || src == NULL, 4161da177e4SLinus Torvalds "source(%p) or dest(%p) buffer is 0", src, dest); 4171da177e4SLinus Torvalds RFALSE(dest_position_before < 0 || src_position < 0, 4181da177e4SLinus Torvalds "source(%d) or dest(%d) key number less than 0", 4191da177e4SLinus Torvalds src_position, dest_position_before); 4201da177e4SLinus Torvalds RFALSE(dest_position_before > B_NR_ITEMS(dest) || 4211da177e4SLinus Torvalds src_position >= B_NR_ITEMS(src), 4221da177e4SLinus Torvalds "invalid position in dest (%d (key number %d)) or in src (%d (key number %d))", 4231da177e4SLinus Torvalds dest_position_before, B_NR_ITEMS(dest), 4241da177e4SLinus Torvalds src_position, B_NR_ITEMS(src)); 4251da177e4SLinus Torvalds RFALSE(B_FREE_SPACE(dest) < KEY_SIZE, 4261da177e4SLinus Torvalds "no enough free space (%d) in dest buffer", B_FREE_SPACE(dest)); 4271da177e4SLinus Torvalds 4281da177e4SLinus Torvalds blkh = B_BLK_HEAD(dest); 4291da177e4SLinus Torvalds nr = blkh_nr_item(blkh); 4301da177e4SLinus Torvalds 4311da177e4SLinus Torvalds /* prepare space for inserting key */ 4324cf5f7adSJeff Mahoney key = internal_key(dest, dest_position_before); 433bd4c625cSLinus Torvalds memmove(key + 1, key, 434bd4c625cSLinus Torvalds (nr - dest_position_before) * KEY_SIZE + (nr + 1) * DC_SIZE); 4351da177e4SLinus Torvalds 4361da177e4SLinus Torvalds /* insert key */ 4374cf5f7adSJeff Mahoney memcpy(key, internal_key(src, src_position), KEY_SIZE); 4381da177e4SLinus Torvalds 4391da177e4SLinus Torvalds /* Change dirt, free space, item number fields. */ 4401da177e4SLinus Torvalds 4411da177e4SLinus Torvalds set_blkh_nr_item(blkh, blkh_nr_item(blkh) + 1); 4421da177e4SLinus Torvalds set_blkh_free_space(blkh, blkh_free_space(blkh) - KEY_SIZE); 4431da177e4SLinus Torvalds 4441da177e4SLinus Torvalds do_balance_mark_internal_dirty(dest_bi->tb, dest, 0); 4451da177e4SLinus Torvalds 4461da177e4SLinus Torvalds if (dest_bi->bi_parent) { 4471da177e4SLinus Torvalds struct disk_child *t_dc; 4481da177e4SLinus Torvalds t_dc = B_N_CHILD(dest_bi->bi_parent, dest_bi->bi_position); 4491da177e4SLinus Torvalds put_dc_size(t_dc, dc_size(t_dc) + KEY_SIZE); 4501da177e4SLinus Torvalds 451bd4c625cSLinus Torvalds do_balance_mark_internal_dirty(dest_bi->tb, dest_bi->bi_parent, 452bd4c625cSLinus Torvalds 0); 4531da177e4SLinus Torvalds } 4541da177e4SLinus Torvalds } 4551da177e4SLinus Torvalds 4561da177e4SLinus Torvalds /* Insert d_key'th (delimiting) key from buffer cfl to tail of dest. 4571da177e4SLinus Torvalds * Copy pointer_amount node pointers and pointer_amount - 1 items from buffer src to buffer dest. 4581da177e4SLinus Torvalds * Replace d_key'th key in buffer cfl. 4591da177e4SLinus Torvalds * Delete pointer_amount items and node pointers from buffer src. 4601da177e4SLinus Torvalds */ 4611da177e4SLinus Torvalds /* this can be invoked both to shift from S to L and from R to S */ 462bd4c625cSLinus Torvalds static void internal_shift_left(int mode, /* INTERNAL_FROM_S_TO_L | INTERNAL_FROM_R_TO_S */ 4631da177e4SLinus Torvalds struct tree_balance *tb, 464bd4c625cSLinus Torvalds int h, int pointer_amount) 4651da177e4SLinus Torvalds { 4661da177e4SLinus Torvalds struct buffer_info dest_bi, src_bi; 4671da177e4SLinus Torvalds struct buffer_head *cf; 4681da177e4SLinus Torvalds int d_key_position; 4691da177e4SLinus Torvalds 470bd4c625cSLinus Torvalds internal_define_dest_src_infos(mode, tb, h, &dest_bi, &src_bi, 471bd4c625cSLinus Torvalds &d_key_position, &cf); 4721da177e4SLinus Torvalds 4731da177e4SLinus Torvalds /*printk("pointer_amount = %d\n",pointer_amount); */ 4741da177e4SLinus Torvalds 4751da177e4SLinus Torvalds if (pointer_amount) { 4761da177e4SLinus Torvalds /* insert delimiting key from common father of dest and src to node dest into position B_NR_ITEM(dest) */ 477bd4c625cSLinus Torvalds internal_insert_key(&dest_bi, B_NR_ITEMS(dest_bi.bi_bh), cf, 478bd4c625cSLinus Torvalds d_key_position); 4791da177e4SLinus Torvalds 4801da177e4SLinus Torvalds if (B_NR_ITEMS(src_bi.bi_bh) == pointer_amount - 1) { 4811da177e4SLinus Torvalds if (src_bi.bi_position /*src->b_item_order */ == 0) 482bd4c625cSLinus Torvalds replace_key(tb, cf, d_key_position, 483bd4c625cSLinus Torvalds src_bi. 484bd4c625cSLinus Torvalds bi_parent /*src->b_parent */ , 0); 4851da177e4SLinus Torvalds } else 486bd4c625cSLinus Torvalds replace_key(tb, cf, d_key_position, src_bi.bi_bh, 487bd4c625cSLinus Torvalds pointer_amount - 1); 4881da177e4SLinus Torvalds } 4891da177e4SLinus Torvalds /* last parameter is del_parameter */ 490bd4c625cSLinus Torvalds internal_move_pointers_items(&dest_bi, &src_bi, FIRST_TO_LAST, 491bd4c625cSLinus Torvalds pointer_amount, 0); 4921da177e4SLinus Torvalds 4931da177e4SLinus Torvalds } 4941da177e4SLinus Torvalds 4951da177e4SLinus Torvalds /* Insert delimiting key to L[h]. 4961da177e4SLinus Torvalds * Copy n node pointers and n - 1 items from buffer S[h] to L[h]. 4971da177e4SLinus Torvalds * Delete n - 1 items and node pointers from buffer S[h]. 4981da177e4SLinus Torvalds */ 4991da177e4SLinus Torvalds /* it always shifts from S[h] to L[h] */ 500bd4c625cSLinus Torvalds static void internal_shift1_left(struct tree_balance *tb, 501bd4c625cSLinus Torvalds int h, int pointer_amount) 5021da177e4SLinus Torvalds { 5031da177e4SLinus Torvalds struct buffer_info dest_bi, src_bi; 5041da177e4SLinus Torvalds struct buffer_head *cf; 5051da177e4SLinus Torvalds int d_key_position; 5061da177e4SLinus Torvalds 507bd4c625cSLinus Torvalds internal_define_dest_src_infos(INTERNAL_SHIFT_FROM_S_TO_L, tb, h, 508bd4c625cSLinus Torvalds &dest_bi, &src_bi, &d_key_position, &cf); 5091da177e4SLinus Torvalds 5101da177e4SLinus Torvalds if (pointer_amount > 0) /* insert lkey[h]-th key from CFL[h] to left neighbor L[h] */ 511bd4c625cSLinus Torvalds internal_insert_key(&dest_bi, B_NR_ITEMS(dest_bi.bi_bh), cf, 512bd4c625cSLinus Torvalds d_key_position); 5131da177e4SLinus Torvalds /* internal_insert_key (tb->L[h], B_NR_ITEM(tb->L[h]), tb->CFL[h], tb->lkey[h]); */ 5141da177e4SLinus Torvalds 5151da177e4SLinus Torvalds /* last parameter is del_parameter */ 516bd4c625cSLinus Torvalds internal_move_pointers_items(&dest_bi, &src_bi, FIRST_TO_LAST, 517bd4c625cSLinus Torvalds pointer_amount, 1); 5181da177e4SLinus Torvalds /* internal_move_pointers_items (tb->L[h], tb->S[h], FIRST_TO_LAST, pointer_amount, 1); */ 5191da177e4SLinus Torvalds } 5201da177e4SLinus Torvalds 5211da177e4SLinus Torvalds /* Insert d_key'th (delimiting) key from buffer cfr to head of dest. 5221da177e4SLinus Torvalds * Copy n node pointers and n - 1 items from buffer src to buffer dest. 5231da177e4SLinus Torvalds * Replace d_key'th key in buffer cfr. 5241da177e4SLinus Torvalds * Delete n items and node pointers from buffer src. 5251da177e4SLinus Torvalds */ 526bd4c625cSLinus Torvalds static void internal_shift_right(int mode, /* INTERNAL_FROM_S_TO_R | INTERNAL_FROM_L_TO_S */ 5271da177e4SLinus Torvalds struct tree_balance *tb, 528bd4c625cSLinus Torvalds int h, int pointer_amount) 5291da177e4SLinus Torvalds { 5301da177e4SLinus Torvalds struct buffer_info dest_bi, src_bi; 5311da177e4SLinus Torvalds struct buffer_head *cf; 5321da177e4SLinus Torvalds int d_key_position; 5331da177e4SLinus Torvalds int nr; 5341da177e4SLinus Torvalds 535bd4c625cSLinus Torvalds internal_define_dest_src_infos(mode, tb, h, &dest_bi, &src_bi, 536bd4c625cSLinus Torvalds &d_key_position, &cf); 5371da177e4SLinus Torvalds 5381da177e4SLinus Torvalds nr = B_NR_ITEMS(src_bi.bi_bh); 5391da177e4SLinus Torvalds 5401da177e4SLinus Torvalds if (pointer_amount > 0) { 5411da177e4SLinus Torvalds /* insert delimiting key from common father of dest and src to dest node into position 0 */ 5421da177e4SLinus Torvalds internal_insert_key(&dest_bi, 0, cf, d_key_position); 5431da177e4SLinus Torvalds if (nr == pointer_amount - 1) { 5441da177e4SLinus Torvalds RFALSE(src_bi.bi_bh != PATH_H_PBUFFER(tb->tb_path, h) /*tb->S[h] */ || 5451da177e4SLinus Torvalds dest_bi.bi_bh != tb->R[h], 5461da177e4SLinus Torvalds "src (%p) must be == tb->S[h](%p) when it disappears", 5471da177e4SLinus Torvalds src_bi.bi_bh, PATH_H_PBUFFER(tb->tb_path, h)); 5481da177e4SLinus Torvalds /* when S[h] disappers replace left delemiting key as well */ 5491da177e4SLinus Torvalds if (tb->CFL[h]) 550bd4c625cSLinus Torvalds replace_key(tb, cf, d_key_position, tb->CFL[h], 551bd4c625cSLinus Torvalds tb->lkey[h]); 5521da177e4SLinus Torvalds } else 553bd4c625cSLinus Torvalds replace_key(tb, cf, d_key_position, src_bi.bi_bh, 554bd4c625cSLinus Torvalds nr - pointer_amount); 5551da177e4SLinus Torvalds } 5561da177e4SLinus Torvalds 5571da177e4SLinus Torvalds /* last parameter is del_parameter */ 558bd4c625cSLinus Torvalds internal_move_pointers_items(&dest_bi, &src_bi, LAST_TO_FIRST, 559bd4c625cSLinus Torvalds pointer_amount, 0); 5601da177e4SLinus Torvalds } 5611da177e4SLinus Torvalds 5621da177e4SLinus Torvalds /* Insert delimiting key to R[h]. 5631da177e4SLinus Torvalds * Copy n node pointers and n - 1 items from buffer S[h] to R[h]. 5641da177e4SLinus Torvalds * Delete n - 1 items and node pointers from buffer S[h]. 5651da177e4SLinus Torvalds */ 5661da177e4SLinus Torvalds /* it always shift from S[h] to R[h] */ 567bd4c625cSLinus Torvalds static void internal_shift1_right(struct tree_balance *tb, 568bd4c625cSLinus Torvalds int h, int pointer_amount) 5691da177e4SLinus Torvalds { 5701da177e4SLinus Torvalds struct buffer_info dest_bi, src_bi; 5711da177e4SLinus Torvalds struct buffer_head *cf; 5721da177e4SLinus Torvalds int d_key_position; 5731da177e4SLinus Torvalds 574bd4c625cSLinus Torvalds internal_define_dest_src_infos(INTERNAL_SHIFT_FROM_S_TO_R, tb, h, 575bd4c625cSLinus Torvalds &dest_bi, &src_bi, &d_key_position, &cf); 5761da177e4SLinus Torvalds 5771da177e4SLinus Torvalds if (pointer_amount > 0) /* insert rkey from CFR[h] to right neighbor R[h] */ 5781da177e4SLinus Torvalds internal_insert_key(&dest_bi, 0, cf, d_key_position); 5791da177e4SLinus Torvalds /* internal_insert_key (tb->R[h], 0, tb->CFR[h], tb->rkey[h]); */ 5801da177e4SLinus Torvalds 5811da177e4SLinus Torvalds /* last parameter is del_parameter */ 582bd4c625cSLinus Torvalds internal_move_pointers_items(&dest_bi, &src_bi, LAST_TO_FIRST, 583bd4c625cSLinus Torvalds pointer_amount, 1); 5841da177e4SLinus Torvalds /* internal_move_pointers_items (tb->R[h], tb->S[h], LAST_TO_FIRST, pointer_amount, 1); */ 5851da177e4SLinus Torvalds } 5861da177e4SLinus Torvalds 5871da177e4SLinus Torvalds /* Delete insert_num node pointers together with their left items 5881da177e4SLinus Torvalds * and balance current node.*/ 5891da177e4SLinus Torvalds static void balance_internal_when_delete(struct tree_balance *tb, 5901da177e4SLinus Torvalds int h, int child_pos) 5911da177e4SLinus Torvalds { 5921da177e4SLinus Torvalds int insert_num; 5931da177e4SLinus Torvalds int n; 5941da177e4SLinus Torvalds struct buffer_head *tbSh = PATH_H_PBUFFER(tb->tb_path, h); 5951da177e4SLinus Torvalds struct buffer_info bi; 5961da177e4SLinus Torvalds 5971da177e4SLinus Torvalds insert_num = tb->insert_size[h] / ((int)(DC_SIZE + KEY_SIZE)); 5981da177e4SLinus Torvalds 5991da177e4SLinus Torvalds /* delete child-node-pointer(s) together with their left item(s) */ 6001da177e4SLinus Torvalds bi.tb = tb; 6011da177e4SLinus Torvalds bi.bi_bh = tbSh; 6021da177e4SLinus Torvalds bi.bi_parent = PATH_H_PPARENT(tb->tb_path, h); 6031da177e4SLinus Torvalds bi.bi_position = PATH_H_POSITION(tb->tb_path, h + 1); 6041da177e4SLinus Torvalds 6051da177e4SLinus Torvalds internal_delete_childs(&bi, child_pos, -insert_num); 6061da177e4SLinus Torvalds 6071da177e4SLinus Torvalds RFALSE(tb->blknum[h] > 1, 6081da177e4SLinus Torvalds "tb->blknum[%d]=%d when insert_size < 0", h, tb->blknum[h]); 6091da177e4SLinus Torvalds 6101da177e4SLinus Torvalds n = B_NR_ITEMS(tbSh); 6111da177e4SLinus Torvalds 6121da177e4SLinus Torvalds if (tb->lnum[h] == 0 && tb->rnum[h] == 0) { 6131da177e4SLinus Torvalds if (tb->blknum[h] == 0) { 6141da177e4SLinus Torvalds /* node S[h] (root of the tree) is empty now */ 6151da177e4SLinus Torvalds struct buffer_head *new_root; 6161da177e4SLinus Torvalds 617bd4c625cSLinus Torvalds RFALSE(n 618bd4c625cSLinus Torvalds || B_FREE_SPACE(tbSh) != 619bd4c625cSLinus Torvalds MAX_CHILD_SIZE(tbSh) - DC_SIZE, 6201da177e4SLinus Torvalds "buffer must have only 0 keys (%d)", n); 621bd4c625cSLinus Torvalds RFALSE(bi.bi_parent, "root has parent (%p)", 622bd4c625cSLinus Torvalds bi.bi_parent); 6231da177e4SLinus Torvalds 6241da177e4SLinus Torvalds /* choose a new root */ 6251da177e4SLinus Torvalds if (!tb->L[h - 1] || !B_NR_ITEMS(tb->L[h - 1])) 6261da177e4SLinus Torvalds new_root = tb->R[h - 1]; 6271da177e4SLinus Torvalds else 6281da177e4SLinus Torvalds new_root = tb->L[h - 1]; 6291da177e4SLinus Torvalds /* switch super block's tree root block number to the new value */ 6301da177e4SLinus Torvalds PUT_SB_ROOT_BLOCK(tb->tb_sb, new_root->b_blocknr); 6311da177e4SLinus Torvalds //REISERFS_SB(tb->tb_sb)->s_rs->s_tree_height --; 632bd4c625cSLinus Torvalds PUT_SB_TREE_HEIGHT(tb->tb_sb, 633bd4c625cSLinus Torvalds SB_TREE_HEIGHT(tb->tb_sb) - 1); 6341da177e4SLinus Torvalds 635bd4c625cSLinus Torvalds do_balance_mark_sb_dirty(tb, 636bd4c625cSLinus Torvalds REISERFS_SB(tb->tb_sb)->s_sbh, 637bd4c625cSLinus Torvalds 1); 6381da177e4SLinus Torvalds /*&&&&&&&&&&&&&&&&&&&&&& */ 6391da177e4SLinus Torvalds if (h > 1) 6401da177e4SLinus Torvalds /* use check_internal if new root is an internal node */ 6411da177e4SLinus Torvalds check_internal(new_root); 6421da177e4SLinus Torvalds /*&&&&&&&&&&&&&&&&&&&&&& */ 6431da177e4SLinus Torvalds 6441da177e4SLinus Torvalds /* do what is needed for buffer thrown from tree */ 6451da177e4SLinus Torvalds reiserfs_invalidate_buffer(tb, tbSh); 6461da177e4SLinus Torvalds return; 6471da177e4SLinus Torvalds } 6481da177e4SLinus Torvalds return; 6491da177e4SLinus Torvalds } 6501da177e4SLinus Torvalds 6511da177e4SLinus Torvalds if (tb->L[h] && tb->lnum[h] == -B_NR_ITEMS(tb->L[h]) - 1) { /* join S[h] with L[h] */ 6521da177e4SLinus Torvalds 6531da177e4SLinus Torvalds RFALSE(tb->rnum[h] != 0, 6541da177e4SLinus Torvalds "invalid tb->rnum[%d]==%d when joining S[h] with L[h]", 6551da177e4SLinus Torvalds h, tb->rnum[h]); 6561da177e4SLinus Torvalds 6571da177e4SLinus Torvalds internal_shift_left(INTERNAL_SHIFT_FROM_S_TO_L, tb, h, n + 1); 6581da177e4SLinus Torvalds reiserfs_invalidate_buffer(tb, tbSh); 6591da177e4SLinus Torvalds 6601da177e4SLinus Torvalds return; 6611da177e4SLinus Torvalds } 6621da177e4SLinus Torvalds 6631da177e4SLinus Torvalds if (tb->R[h] && tb->rnum[h] == -B_NR_ITEMS(tb->R[h]) - 1) { /* join S[h] with R[h] */ 6641da177e4SLinus Torvalds RFALSE(tb->lnum[h] != 0, 6651da177e4SLinus Torvalds "invalid tb->lnum[%d]==%d when joining S[h] with R[h]", 6661da177e4SLinus Torvalds h, tb->lnum[h]); 6671da177e4SLinus Torvalds 6681da177e4SLinus Torvalds internal_shift_right(INTERNAL_SHIFT_FROM_S_TO_R, tb, h, n + 1); 6691da177e4SLinus Torvalds 6701da177e4SLinus Torvalds reiserfs_invalidate_buffer(tb, tbSh); 6711da177e4SLinus Torvalds return; 6721da177e4SLinus Torvalds } 6731da177e4SLinus Torvalds 6741da177e4SLinus Torvalds if (tb->lnum[h] < 0) { /* borrow from left neighbor L[h] */ 6751da177e4SLinus Torvalds RFALSE(tb->rnum[h] != 0, 676bd4c625cSLinus Torvalds "wrong tb->rnum[%d]==%d when borrow from L[h]", h, 677bd4c625cSLinus Torvalds tb->rnum[h]); 6781da177e4SLinus Torvalds /*internal_shift_right (tb, h, tb->L[h], tb->CFL[h], tb->lkey[h], tb->S[h], -tb->lnum[h]); */ 679bd4c625cSLinus Torvalds internal_shift_right(INTERNAL_SHIFT_FROM_L_TO_S, tb, h, 680bd4c625cSLinus Torvalds -tb->lnum[h]); 6811da177e4SLinus Torvalds return; 6821da177e4SLinus Torvalds } 6831da177e4SLinus Torvalds 6841da177e4SLinus Torvalds if (tb->rnum[h] < 0) { /* borrow from right neighbor R[h] */ 6851da177e4SLinus Torvalds RFALSE(tb->lnum[h] != 0, 6861da177e4SLinus Torvalds "invalid tb->lnum[%d]==%d when borrow from R[h]", 6871da177e4SLinus Torvalds h, tb->lnum[h]); 6881da177e4SLinus Torvalds 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]); */ 6891da177e4SLinus Torvalds return; 6901da177e4SLinus Torvalds } 6911da177e4SLinus Torvalds 6921da177e4SLinus Torvalds if (tb->lnum[h] > 0) { /* split S[h] into two parts and put them into neighbors */ 6931da177e4SLinus Torvalds RFALSE(tb->rnum[h] == 0 || tb->lnum[h] + tb->rnum[h] != n + 1, 6941da177e4SLinus Torvalds "invalid tb->lnum[%d]==%d or tb->rnum[%d]==%d when S[h](item number == %d) is split between them", 6951da177e4SLinus Torvalds h, tb->lnum[h], h, tb->rnum[h], n); 6961da177e4SLinus Torvalds 6971da177e4SLinus Torvalds 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]); */ 698bd4c625cSLinus Torvalds internal_shift_right(INTERNAL_SHIFT_FROM_S_TO_R, tb, h, 699bd4c625cSLinus Torvalds tb->rnum[h]); 7001da177e4SLinus Torvalds 7011da177e4SLinus Torvalds reiserfs_invalidate_buffer(tb, tbSh); 7021da177e4SLinus Torvalds 7031da177e4SLinus Torvalds return; 7041da177e4SLinus Torvalds } 705c3a9c210SJeff Mahoney reiserfs_panic(tb->tb_sb, "ibalance-2", 706c3a9c210SJeff Mahoney "unexpected tb->lnum[%d]==%d or tb->rnum[%d]==%d", 7071da177e4SLinus Torvalds h, tb->lnum[h], h, tb->rnum[h]); 7081da177e4SLinus Torvalds } 7091da177e4SLinus Torvalds 7101da177e4SLinus Torvalds /* Replace delimiting key of buffers L[h] and S[h] by the given key.*/ 711bd4c625cSLinus Torvalds static void replace_lkey(struct tree_balance *tb, int h, struct item_head *key) 7121da177e4SLinus Torvalds { 7131da177e4SLinus Torvalds RFALSE(tb->L[h] == NULL || tb->CFL[h] == NULL, 7141da177e4SLinus Torvalds "L[h](%p) and CFL[h](%p) must exist in replace_lkey", 7151da177e4SLinus Torvalds tb->L[h], tb->CFL[h]); 7161da177e4SLinus Torvalds 7171da177e4SLinus Torvalds if (B_NR_ITEMS(PATH_H_PBUFFER(tb->tb_path, h)) == 0) 7181da177e4SLinus Torvalds return; 7191da177e4SLinus Torvalds 7204cf5f7adSJeff Mahoney memcpy(internal_key(tb->CFL[h], tb->lkey[h]), key, KEY_SIZE); 7211da177e4SLinus Torvalds 7221da177e4SLinus Torvalds do_balance_mark_internal_dirty(tb, tb->CFL[h], 0); 7231da177e4SLinus Torvalds } 7241da177e4SLinus Torvalds 7251da177e4SLinus Torvalds /* Replace delimiting key of buffers S[h] and R[h] by the given key.*/ 726bd4c625cSLinus Torvalds static void replace_rkey(struct tree_balance *tb, int h, struct item_head *key) 7271da177e4SLinus Torvalds { 7281da177e4SLinus Torvalds RFALSE(tb->R[h] == NULL || tb->CFR[h] == NULL, 7291da177e4SLinus Torvalds "R[h](%p) and CFR[h](%p) must exist in replace_rkey", 7301da177e4SLinus Torvalds tb->R[h], tb->CFR[h]); 7311da177e4SLinus Torvalds RFALSE(B_NR_ITEMS(tb->R[h]) == 0, 7321da177e4SLinus Torvalds "R[h] can not be empty if it exists (item number=%d)", 7331da177e4SLinus Torvalds B_NR_ITEMS(tb->R[h])); 7341da177e4SLinus Torvalds 7354cf5f7adSJeff Mahoney memcpy(internal_key(tb->CFR[h], tb->rkey[h]), key, KEY_SIZE); 7361da177e4SLinus Torvalds 7371da177e4SLinus Torvalds do_balance_mark_internal_dirty(tb, tb->CFR[h], 0); 7381da177e4SLinus Torvalds } 7391da177e4SLinus Torvalds 7401da177e4SLinus Torvalds int balance_internal(struct tree_balance *tb, /* tree_balance structure */ 7411da177e4SLinus Torvalds int h, /* level of the tree */ 742bd4c625cSLinus Torvalds int child_pos, struct item_head *insert_key, /* key for insertion on higher level */ 7431da177e4SLinus Torvalds struct buffer_head **insert_ptr /* node for insertion on higher level */ 7441da177e4SLinus Torvalds ) 7451da177e4SLinus Torvalds /* if inserting/pasting 7461da177e4SLinus Torvalds { 7471da177e4SLinus Torvalds child_pos is the position of the node-pointer in S[h] that * 7481da177e4SLinus Torvalds pointed to S[h-1] before balancing of the h-1 level; * 7491da177e4SLinus Torvalds this means that new pointers and items must be inserted AFTER * 7501da177e4SLinus Torvalds child_pos 7511da177e4SLinus Torvalds } 7521da177e4SLinus Torvalds else 7531da177e4SLinus Torvalds { 7541da177e4SLinus Torvalds it is the position of the leftmost pointer that must be deleted (together with 7551da177e4SLinus Torvalds its corresponding key to the left of the pointer) 7561da177e4SLinus Torvalds as a result of the previous level's balancing. 7571da177e4SLinus Torvalds } 7581da177e4SLinus Torvalds */ 7591da177e4SLinus Torvalds { 7601da177e4SLinus Torvalds struct buffer_head *tbSh = PATH_H_PBUFFER(tb->tb_path, h); 7611da177e4SLinus Torvalds struct buffer_info bi; 7621da177e4SLinus Torvalds int order; /* we return this: it is 0 if there is no S[h], else it is tb->S[h]->b_item_order */ 7631da177e4SLinus Torvalds int insert_num, n, k; 7641da177e4SLinus Torvalds struct buffer_head *S_new; 7651da177e4SLinus Torvalds struct item_head new_insert_key; 7661da177e4SLinus Torvalds struct buffer_head *new_insert_ptr = NULL; 7671da177e4SLinus Torvalds struct item_head *new_insert_key_addr = insert_key; 7681da177e4SLinus Torvalds 7691da177e4SLinus Torvalds RFALSE(h < 1, "h (%d) can not be < 1 on internal level", h); 7701da177e4SLinus Torvalds 7711da177e4SLinus Torvalds PROC_INFO_INC(tb->tb_sb, balance_at[h]); 7721da177e4SLinus Torvalds 773bd4c625cSLinus Torvalds order = 774bd4c625cSLinus Torvalds (tbSh) ? PATH_H_POSITION(tb->tb_path, 775bd4c625cSLinus Torvalds h + 1) /*tb->S[h]->b_item_order */ : 0; 7761da177e4SLinus Torvalds 7771da177e4SLinus Torvalds /* Using insert_size[h] calculate the number insert_num of items 7781da177e4SLinus Torvalds that must be inserted to or deleted from S[h]. */ 7791da177e4SLinus Torvalds insert_num = tb->insert_size[h] / ((int)(KEY_SIZE + DC_SIZE)); 7801da177e4SLinus Torvalds 7811da177e4SLinus Torvalds /* Check whether insert_num is proper * */ 7821da177e4SLinus Torvalds RFALSE(insert_num < -2 || insert_num > 2, 7831da177e4SLinus Torvalds "incorrect number of items inserted to the internal node (%d)", 7841da177e4SLinus Torvalds insert_num); 7851da177e4SLinus Torvalds RFALSE(h > 1 && (insert_num > 1 || insert_num < -1), 7861da177e4SLinus Torvalds "incorrect number of items (%d) inserted to the internal node on a level (h=%d) higher than last internal level", 7871da177e4SLinus Torvalds insert_num, h); 7881da177e4SLinus Torvalds 7891da177e4SLinus Torvalds /* Make balance in case insert_num < 0 */ 7901da177e4SLinus Torvalds if (insert_num < 0) { 7911da177e4SLinus Torvalds balance_internal_when_delete(tb, h, child_pos); 7921da177e4SLinus Torvalds return order; 7931da177e4SLinus Torvalds } 7941da177e4SLinus Torvalds 7951da177e4SLinus Torvalds k = 0; 7961da177e4SLinus Torvalds if (tb->lnum[h] > 0) { 7971da177e4SLinus Torvalds /* shift lnum[h] items from S[h] to the left neighbor L[h]. 7981da177e4SLinus Torvalds check how many of new items fall into L[h] or CFL[h] after 7991da177e4SLinus Torvalds shifting */ 8001da177e4SLinus Torvalds n = B_NR_ITEMS(tb->L[h]); /* number of items in L[h] */ 8011da177e4SLinus Torvalds if (tb->lnum[h] <= child_pos) { 8021da177e4SLinus Torvalds /* new items don't fall into L[h] or CFL[h] */ 803bd4c625cSLinus Torvalds internal_shift_left(INTERNAL_SHIFT_FROM_S_TO_L, tb, h, 804bd4c625cSLinus Torvalds tb->lnum[h]); 8051da177e4SLinus Torvalds /*internal_shift_left (tb->L[h],tb->CFL[h],tb->lkey[h],tbSh,tb->lnum[h]); */ 8061da177e4SLinus Torvalds child_pos -= tb->lnum[h]; 8071da177e4SLinus Torvalds } else if (tb->lnum[h] > child_pos + insert_num) { 8081da177e4SLinus Torvalds /* all new items fall into L[h] */ 809bd4c625cSLinus Torvalds internal_shift_left(INTERNAL_SHIFT_FROM_S_TO_L, tb, h, 810bd4c625cSLinus Torvalds tb->lnum[h] - insert_num); 8111da177e4SLinus Torvalds /* internal_shift_left(tb->L[h],tb->CFL[h],tb->lkey[h],tbSh, 8121da177e4SLinus Torvalds tb->lnum[h]-insert_num); 8131da177e4SLinus Torvalds */ 8141da177e4SLinus Torvalds /* insert insert_num keys and node-pointers into L[h] */ 8151da177e4SLinus Torvalds bi.tb = tb; 8161da177e4SLinus Torvalds bi.bi_bh = tb->L[h]; 8171da177e4SLinus Torvalds bi.bi_parent = tb->FL[h]; 8181da177e4SLinus Torvalds bi.bi_position = get_left_neighbor_position(tb, h); 819bd4c625cSLinus Torvalds internal_insert_childs(&bi, 820bd4c625cSLinus Torvalds /*tb->L[h], tb->S[h-1]->b_next */ 821bd4c625cSLinus Torvalds n + child_pos + 1, 822bd4c625cSLinus Torvalds insert_num, insert_key, 823bd4c625cSLinus Torvalds insert_ptr); 8241da177e4SLinus Torvalds 8251da177e4SLinus Torvalds insert_num = 0; 8261da177e4SLinus Torvalds } else { 8271da177e4SLinus Torvalds struct disk_child *dc; 8281da177e4SLinus Torvalds 8291da177e4SLinus Torvalds /* some items fall into L[h] or CFL[h], but some don't fall */ 8301da177e4SLinus Torvalds internal_shift1_left(tb, h, child_pos + 1); 8311da177e4SLinus Torvalds /* calculate number of new items that fall into L[h] */ 8321da177e4SLinus Torvalds k = tb->lnum[h] - child_pos - 1; 8331da177e4SLinus Torvalds bi.tb = tb; 8341da177e4SLinus Torvalds bi.bi_bh = tb->L[h]; 8351da177e4SLinus Torvalds bi.bi_parent = tb->FL[h]; 8361da177e4SLinus Torvalds bi.bi_position = get_left_neighbor_position(tb, h); 837bd4c625cSLinus Torvalds internal_insert_childs(&bi, 838bd4c625cSLinus Torvalds /*tb->L[h], tb->S[h-1]->b_next, */ 839bd4c625cSLinus Torvalds n + child_pos + 1, k, 8401da177e4SLinus Torvalds insert_key, insert_ptr); 8411da177e4SLinus Torvalds 8421da177e4SLinus Torvalds replace_lkey(tb, h, insert_key + k); 8431da177e4SLinus Torvalds 8441da177e4SLinus Torvalds /* replace the first node-ptr in S[h] by node-ptr to insert_ptr[k] */ 8451da177e4SLinus Torvalds dc = B_N_CHILD(tbSh, 0); 846bd4c625cSLinus Torvalds put_dc_size(dc, 847bd4c625cSLinus Torvalds MAX_CHILD_SIZE(insert_ptr[k]) - 848bd4c625cSLinus Torvalds B_FREE_SPACE(insert_ptr[k])); 8491da177e4SLinus Torvalds put_dc_block_number(dc, insert_ptr[k]->b_blocknr); 8501da177e4SLinus Torvalds 8511da177e4SLinus Torvalds do_balance_mark_internal_dirty(tb, tbSh, 0); 8521da177e4SLinus Torvalds 8531da177e4SLinus Torvalds k++; 8541da177e4SLinus Torvalds insert_key += k; 8551da177e4SLinus Torvalds insert_ptr += k; 8561da177e4SLinus Torvalds insert_num -= k; 8571da177e4SLinus Torvalds child_pos = 0; 8581da177e4SLinus Torvalds } 859bd4c625cSLinus Torvalds } 860bd4c625cSLinus Torvalds /* tb->lnum[h] > 0 */ 8611da177e4SLinus Torvalds if (tb->rnum[h] > 0) { 8621da177e4SLinus Torvalds /*shift rnum[h] items from S[h] to the right neighbor R[h] */ 8631da177e4SLinus Torvalds /* check how many of new items fall into R or CFR after shifting */ 8641da177e4SLinus Torvalds n = B_NR_ITEMS(tbSh); /* number of items in S[h] */ 8651da177e4SLinus Torvalds if (n - tb->rnum[h] >= child_pos) 8661da177e4SLinus Torvalds /* new items fall into S[h] */ 8671da177e4SLinus Torvalds /*internal_shift_right(tb,h,tbSh,tb->CFR[h],tb->rkey[h],tb->R[h],tb->rnum[h]); */ 868bd4c625cSLinus Torvalds internal_shift_right(INTERNAL_SHIFT_FROM_S_TO_R, tb, h, 869bd4c625cSLinus Torvalds tb->rnum[h]); 870bd4c625cSLinus Torvalds else if (n + insert_num - tb->rnum[h] < child_pos) { 8711da177e4SLinus Torvalds /* all new items fall into R[h] */ 8721da177e4SLinus Torvalds /*internal_shift_right(tb,h,tbSh,tb->CFR[h],tb->rkey[h],tb->R[h], 8731da177e4SLinus Torvalds tb->rnum[h] - insert_num); */ 874bd4c625cSLinus Torvalds internal_shift_right(INTERNAL_SHIFT_FROM_S_TO_R, tb, h, 875bd4c625cSLinus Torvalds tb->rnum[h] - insert_num); 8761da177e4SLinus Torvalds 8771da177e4SLinus Torvalds /* insert insert_num keys and node-pointers into R[h] */ 8781da177e4SLinus Torvalds bi.tb = tb; 8791da177e4SLinus Torvalds bi.bi_bh = tb->R[h]; 8801da177e4SLinus Torvalds bi.bi_parent = tb->FR[h]; 8811da177e4SLinus Torvalds bi.bi_position = get_right_neighbor_position(tb, h); 882bd4c625cSLinus Torvalds internal_insert_childs(&bi, 883bd4c625cSLinus Torvalds /*tb->R[h],tb->S[h-1]->b_next */ 884bd4c625cSLinus Torvalds child_pos - n - insert_num + 885bd4c625cSLinus Torvalds tb->rnum[h] - 1, 886bd4c625cSLinus Torvalds insert_num, insert_key, 887bd4c625cSLinus Torvalds insert_ptr); 8881da177e4SLinus Torvalds insert_num = 0; 889bd4c625cSLinus Torvalds } else { 8901da177e4SLinus Torvalds struct disk_child *dc; 8911da177e4SLinus Torvalds 8921da177e4SLinus Torvalds /* one of the items falls into CFR[h] */ 8931da177e4SLinus Torvalds internal_shift1_right(tb, h, n - child_pos + 1); 8941da177e4SLinus Torvalds /* calculate number of new items that fall into R[h] */ 8951da177e4SLinus Torvalds k = tb->rnum[h] - n + child_pos - 1; 8961da177e4SLinus Torvalds bi.tb = tb; 8971da177e4SLinus Torvalds bi.bi_bh = tb->R[h]; 8981da177e4SLinus Torvalds bi.bi_parent = tb->FR[h]; 8991da177e4SLinus Torvalds bi.bi_position = get_right_neighbor_position(tb, h); 900bd4c625cSLinus Torvalds internal_insert_childs(&bi, 901bd4c625cSLinus Torvalds /*tb->R[h], tb->R[h]->b_child, */ 902bd4c625cSLinus Torvalds 0, k, insert_key + 1, 903bd4c625cSLinus Torvalds insert_ptr + 1); 9041da177e4SLinus Torvalds 9051da177e4SLinus Torvalds replace_rkey(tb, h, insert_key + insert_num - k - 1); 9061da177e4SLinus Torvalds 9071da177e4SLinus Torvalds /* replace the first node-ptr in R[h] by node-ptr insert_ptr[insert_num-k-1] */ 9081da177e4SLinus Torvalds dc = B_N_CHILD(tb->R[h], 0); 909bd4c625cSLinus Torvalds put_dc_size(dc, 910bd4c625cSLinus Torvalds MAX_CHILD_SIZE(insert_ptr 911bd4c625cSLinus Torvalds [insert_num - k - 1]) - 912bd4c625cSLinus Torvalds B_FREE_SPACE(insert_ptr 913bd4c625cSLinus Torvalds [insert_num - k - 1])); 914bd4c625cSLinus Torvalds put_dc_block_number(dc, 915bd4c625cSLinus Torvalds insert_ptr[insert_num - k - 916bd4c625cSLinus Torvalds 1]->b_blocknr); 9171da177e4SLinus Torvalds 9181da177e4SLinus Torvalds do_balance_mark_internal_dirty(tb, tb->R[h], 0); 9191da177e4SLinus Torvalds 9201da177e4SLinus Torvalds insert_num -= (k + 1); 9211da177e4SLinus Torvalds } 9221da177e4SLinus Torvalds } 9231da177e4SLinus Torvalds 9241da177e4SLinus Torvalds /** Fill new node that appears instead of S[h] **/ 9251da177e4SLinus Torvalds RFALSE(tb->blknum[h] > 2, "blknum can not be > 2 for internal level"); 9261da177e4SLinus Torvalds RFALSE(tb->blknum[h] < 0, "blknum can not be < 0"); 9271da177e4SLinus Torvalds 928bd4c625cSLinus Torvalds if (!tb->blknum[h]) { /* node S[h] is empty now */ 9291da177e4SLinus Torvalds RFALSE(!tbSh, "S[h] is equal NULL"); 9301da177e4SLinus Torvalds 9311da177e4SLinus Torvalds /* do what is needed for buffer thrown from tree */ 9321da177e4SLinus Torvalds reiserfs_invalidate_buffer(tb, tbSh); 9331da177e4SLinus Torvalds return order; 9341da177e4SLinus Torvalds } 9351da177e4SLinus Torvalds 9361da177e4SLinus Torvalds if (!tbSh) { 9371da177e4SLinus Torvalds /* create new root */ 9381da177e4SLinus Torvalds struct disk_child *dc; 9391da177e4SLinus Torvalds struct buffer_head *tbSh_1 = PATH_H_PBUFFER(tb->tb_path, h - 1); 9401da177e4SLinus Torvalds struct block_head *blkh; 9411da177e4SLinus Torvalds 9421da177e4SLinus Torvalds if (tb->blknum[h] != 1) 943c3a9c210SJeff Mahoney reiserfs_panic(NULL, "ibalance-3", "One new node " 944c3a9c210SJeff Mahoney "required for creating the new root"); 9451da177e4SLinus Torvalds /* S[h] = empty buffer from the list FEB. */ 9461da177e4SLinus Torvalds tbSh = get_FEB(tb); 9471da177e4SLinus Torvalds blkh = B_BLK_HEAD(tbSh); 9481da177e4SLinus Torvalds set_blkh_level(blkh, h + 1); 9491da177e4SLinus Torvalds 9501da177e4SLinus Torvalds /* Put the unique node-pointer to S[h] that points to S[h-1]. */ 9511da177e4SLinus Torvalds 9521da177e4SLinus Torvalds dc = B_N_CHILD(tbSh, 0); 9531da177e4SLinus Torvalds put_dc_block_number(dc, tbSh_1->b_blocknr); 954bd4c625cSLinus Torvalds put_dc_size(dc, 955bd4c625cSLinus Torvalds (MAX_CHILD_SIZE(tbSh_1) - B_FREE_SPACE(tbSh_1))); 9561da177e4SLinus Torvalds 9571da177e4SLinus Torvalds tb->insert_size[h] -= DC_SIZE; 9581da177e4SLinus Torvalds set_blkh_free_space(blkh, blkh_free_space(blkh) - DC_SIZE); 9591da177e4SLinus Torvalds 9601da177e4SLinus Torvalds do_balance_mark_internal_dirty(tb, tbSh, 0); 9611da177e4SLinus Torvalds 9621da177e4SLinus Torvalds /*&&&&&&&&&&&&&&&&&&&&&&&& */ 9631da177e4SLinus Torvalds check_internal(tbSh); 9641da177e4SLinus Torvalds /*&&&&&&&&&&&&&&&&&&&&&&&& */ 9651da177e4SLinus Torvalds 9661da177e4SLinus Torvalds /* put new root into path structure */ 967bd4c625cSLinus Torvalds PATH_OFFSET_PBUFFER(tb->tb_path, ILLEGAL_PATH_ELEMENT_OFFSET) = 968bd4c625cSLinus Torvalds tbSh; 9691da177e4SLinus Torvalds 9701da177e4SLinus Torvalds /* Change root in structure super block. */ 9711da177e4SLinus Torvalds PUT_SB_ROOT_BLOCK(tb->tb_sb, tbSh->b_blocknr); 9721da177e4SLinus Torvalds PUT_SB_TREE_HEIGHT(tb->tb_sb, SB_TREE_HEIGHT(tb->tb_sb) + 1); 9731da177e4SLinus Torvalds do_balance_mark_sb_dirty(tb, REISERFS_SB(tb->tb_sb)->s_sbh, 1); 9741da177e4SLinus Torvalds } 9751da177e4SLinus Torvalds 9761da177e4SLinus Torvalds if (tb->blknum[h] == 2) { 9771da177e4SLinus Torvalds int snum; 9781da177e4SLinus Torvalds struct buffer_info dest_bi, src_bi; 9791da177e4SLinus Torvalds 9801da177e4SLinus Torvalds /* S_new = free buffer from list FEB */ 9811da177e4SLinus Torvalds S_new = get_FEB(tb); 9821da177e4SLinus Torvalds 9831da177e4SLinus Torvalds set_blkh_level(B_BLK_HEAD(S_new), h + 1); 9841da177e4SLinus Torvalds 9851da177e4SLinus Torvalds dest_bi.tb = tb; 9861da177e4SLinus Torvalds dest_bi.bi_bh = S_new; 9871da177e4SLinus Torvalds dest_bi.bi_parent = NULL; 9881da177e4SLinus Torvalds dest_bi.bi_position = 0; 9891da177e4SLinus Torvalds src_bi.tb = tb; 9901da177e4SLinus Torvalds src_bi.bi_bh = tbSh; 9911da177e4SLinus Torvalds src_bi.bi_parent = PATH_H_PPARENT(tb->tb_path, h); 9921da177e4SLinus Torvalds src_bi.bi_position = PATH_H_POSITION(tb->tb_path, h + 1); 9931da177e4SLinus Torvalds 9941da177e4SLinus Torvalds n = B_NR_ITEMS(tbSh); /* number of items in S[h] */ 9951da177e4SLinus Torvalds snum = (insert_num + n + 1) / 2; 9961da177e4SLinus Torvalds if (n - snum >= child_pos) { 9971da177e4SLinus Torvalds /* new items don't fall into S_new */ 9981da177e4SLinus Torvalds /* store the delimiting key for the next level */ 9991da177e4SLinus Torvalds /* new_insert_key = (n - snum)'th key in S[h] */ 10004cf5f7adSJeff Mahoney memcpy(&new_insert_key, internal_key(tbSh, n - snum), 10011da177e4SLinus Torvalds KEY_SIZE); 10021da177e4SLinus Torvalds /* last parameter is del_par */ 1003bd4c625cSLinus Torvalds internal_move_pointers_items(&dest_bi, &src_bi, 1004bd4c625cSLinus Torvalds LAST_TO_FIRST, snum, 0); 10051da177e4SLinus Torvalds /* internal_move_pointers_items(S_new, tbSh, LAST_TO_FIRST, snum, 0); */ 10061da177e4SLinus Torvalds } else if (n + insert_num - snum < child_pos) { 10071da177e4SLinus Torvalds /* all new items fall into S_new */ 10081da177e4SLinus Torvalds /* store the delimiting key for the next level */ 10091da177e4SLinus Torvalds /* new_insert_key = (n + insert_item - snum)'th key in S[h] */ 1010bd4c625cSLinus Torvalds memcpy(&new_insert_key, 10114cf5f7adSJeff Mahoney internal_key(tbSh, n + insert_num - snum), 10121da177e4SLinus Torvalds KEY_SIZE); 10131da177e4SLinus Torvalds /* last parameter is del_par */ 1014bd4c625cSLinus Torvalds internal_move_pointers_items(&dest_bi, &src_bi, 1015bd4c625cSLinus Torvalds LAST_TO_FIRST, 1016bd4c625cSLinus Torvalds snum - insert_num, 0); 10171da177e4SLinus Torvalds /* internal_move_pointers_items(S_new,tbSh,1,snum - insert_num,0); */ 10181da177e4SLinus Torvalds 10191da177e4SLinus Torvalds /* insert insert_num keys and node-pointers into S_new */ 1020bd4c625cSLinus Torvalds internal_insert_childs(&dest_bi, 1021bd4c625cSLinus Torvalds /*S_new,tb->S[h-1]->b_next, */ 1022bd4c625cSLinus Torvalds child_pos - n - insert_num + 1023bd4c625cSLinus Torvalds snum - 1, 1024bd4c625cSLinus Torvalds insert_num, insert_key, 1025bd4c625cSLinus Torvalds insert_ptr); 10261da177e4SLinus Torvalds 10271da177e4SLinus Torvalds insert_num = 0; 10281da177e4SLinus Torvalds } else { 10291da177e4SLinus Torvalds struct disk_child *dc; 10301da177e4SLinus Torvalds 10311da177e4SLinus Torvalds /* some items fall into S_new, but some don't fall */ 10321da177e4SLinus Torvalds /* last parameter is del_par */ 1033bd4c625cSLinus Torvalds internal_move_pointers_items(&dest_bi, &src_bi, 1034bd4c625cSLinus Torvalds LAST_TO_FIRST, 1035bd4c625cSLinus Torvalds n - child_pos + 1, 1); 10361da177e4SLinus Torvalds /* internal_move_pointers_items(S_new,tbSh,1,n - child_pos + 1,1); */ 10371da177e4SLinus Torvalds /* calculate number of new items that fall into S_new */ 10381da177e4SLinus Torvalds k = snum - n + child_pos - 1; 10391da177e4SLinus Torvalds 1040bd4c625cSLinus Torvalds internal_insert_childs(&dest_bi, /*S_new, */ 0, k, 1041bd4c625cSLinus Torvalds insert_key + 1, insert_ptr + 1); 10421da177e4SLinus Torvalds 10431da177e4SLinus Torvalds /* new_insert_key = insert_key[insert_num - k - 1] */ 10441da177e4SLinus Torvalds memcpy(&new_insert_key, insert_key + insert_num - k - 1, 10451da177e4SLinus Torvalds KEY_SIZE); 10461da177e4SLinus Torvalds /* replace first node-ptr in S_new by node-ptr to insert_ptr[insert_num-k-1] */ 10471da177e4SLinus Torvalds 10481da177e4SLinus Torvalds dc = B_N_CHILD(S_new, 0); 1049bd4c625cSLinus Torvalds put_dc_size(dc, 1050bd4c625cSLinus Torvalds (MAX_CHILD_SIZE 1051bd4c625cSLinus Torvalds (insert_ptr[insert_num - k - 1]) - 1052bd4c625cSLinus Torvalds B_FREE_SPACE(insert_ptr 1053bd4c625cSLinus Torvalds [insert_num - k - 1]))); 1054bd4c625cSLinus Torvalds put_dc_block_number(dc, 1055bd4c625cSLinus Torvalds insert_ptr[insert_num - k - 1056bd4c625cSLinus Torvalds 1]->b_blocknr); 10571da177e4SLinus Torvalds 10581da177e4SLinus Torvalds do_balance_mark_internal_dirty(tb, S_new, 0); 10591da177e4SLinus Torvalds 10601da177e4SLinus Torvalds insert_num -= (k + 1); 10611da177e4SLinus Torvalds } 10621da177e4SLinus Torvalds /* new_insert_ptr = node_pointer to S_new */ 10631da177e4SLinus Torvalds new_insert_ptr = S_new; 10641da177e4SLinus Torvalds 1065bd4c625cSLinus Torvalds RFALSE(!buffer_journaled(S_new) || buffer_journal_dirty(S_new) 1066bd4c625cSLinus Torvalds || buffer_dirty(S_new), "cm-00001: bad S_new (%b)", 1067bd4c625cSLinus Torvalds S_new); 10681da177e4SLinus Torvalds 10691da177e4SLinus Torvalds // S_new is released in unfix_nodes 10701da177e4SLinus Torvalds } 10711da177e4SLinus Torvalds 10721da177e4SLinus Torvalds n = B_NR_ITEMS(tbSh); /*number of items in S[h] */ 10731da177e4SLinus Torvalds 10741da177e4SLinus Torvalds if (0 <= child_pos && child_pos <= n && insert_num > 0) { 10751da177e4SLinus Torvalds bi.tb = tb; 10761da177e4SLinus Torvalds bi.bi_bh = tbSh; 10771da177e4SLinus Torvalds bi.bi_parent = PATH_H_PPARENT(tb->tb_path, h); 10781da177e4SLinus Torvalds bi.bi_position = PATH_H_POSITION(tb->tb_path, h + 1); 1079bd4c625cSLinus Torvalds internal_insert_childs(&bi, /*tbSh, */ 10801da177e4SLinus Torvalds /* ( tb->S[h-1]->b_parent == tb->S[h] ) ? tb->S[h-1]->b_next : tb->S[h]->b_child->b_next, */ 1081bd4c625cSLinus Torvalds child_pos, insert_num, insert_key, 1082bd4c625cSLinus Torvalds insert_ptr); 10831da177e4SLinus Torvalds } 10841da177e4SLinus Torvalds 10851da177e4SLinus Torvalds memcpy(new_insert_key_addr, &new_insert_key, KEY_SIZE); 10861da177e4SLinus Torvalds insert_ptr[0] = new_insert_ptr; 10871da177e4SLinus Torvalds 10881da177e4SLinus Torvalds return order; 10891da177e4SLinus Torvalds } 1090