/* Insert n_src'th key of buffer src before n_dest'th key of buffer dest. */ static void internal_insert_key(struct buffer_info *dest_bi, int dest_position_before, /* insert key before key with n_dest number */ struct buffer_head *src, int src_position) { struct buffer_head *dest = dest_bi->bi_bh; int nr; struct block_head *blkh; struct reiserfs_key *key; RFALSE(dest == NULL || src == NULL, "source(%p) or dest(%p) buffer is 0", src, dest); RFALSE(dest_position_before < 0 || src_position < 0, "source(%d) or dest(%d) key number less than 0", src_position, dest_position_before); RFALSE(dest_position_before > B_NR_ITEMS(dest) || src_position >= B_NR_ITEMS(src), "invalid position in dest (%d (key number %d)) or in src (%d (key number %d))", dest_position_before, B_NR_ITEMS(dest), src_position, B_NR_ITEMS(src)); RFALSE(B_FREE_SPACE(dest) < KEY_SIZE, "no enough free space (%d) in dest buffer", B_FREE_SPACE(dest)); blkh = B_BLK_HEAD(dest); nr = blkh_nr_item(blkh); /* prepare space for inserting key */ key = B_N_PDELIM_KEY(dest, dest_position_before); memmove(key + 1, key, (nr - dest_position_before) * KEY_SIZE + (nr + 1) * DC_SIZE); /* insert key */ memcpy(key, B_N_PDELIM_KEY(src, src_position), KEY_SIZE); /* Change dirt, free space, item number fields. */ set_blkh_nr_item(blkh, blkh_nr_item(blkh) + 1); set_blkh_free_space(blkh, blkh_free_space(blkh) - KEY_SIZE); do_balance_mark_internal_dirty(dest_bi->tb, dest, 0); if (dest_bi->bi_parent) { struct disk_child *t_dc; t_dc = B_N_CHILD(dest_bi->bi_parent, dest_bi->bi_position); put_dc_size(t_dc, dc_size(t_dc) + KEY_SIZE); do_balance_mark_internal_dirty(dest_bi->tb, dest_bi->bi_parent, 0); } }
/* this prints internal nodes (4 keys/items in line) (dc_number, dc_size)[k_dirid, k_objectid, k_offset, k_uniqueness](dc_number, dc_size)...*/ static int print_internal(struct buffer_head *bh, int first, int last) { struct reiserfs_key *key; struct disk_child *dc; int i; int from, to; if (!B_IS_KEYS_LEVEL(bh)) return 1; check_internal(bh); if (first == -1) { from = 0; to = B_NR_ITEMS(bh); } else { from = first; to = last < B_NR_ITEMS(bh) ? last : B_NR_ITEMS(bh); } reiserfs_printk("INTERNAL NODE (%ld) contains %z\n", bh->b_blocknr, bh); dc = B_N_CHILD(bh, from); reiserfs_printk("PTR %d: %y ", from, dc); for (i = from, key = B_N_PDELIM_KEY(bh, from), dc++; i < to; i++, key++, dc++) { reiserfs_printk("KEY %d: %k PTR %d: %y ", i, key, i + 1, dc); if (i && i % 4 == 0) printk("\n"); } printk("\n"); return 0; }
static struct key * _get_rkey (struct path * path) { int pos, offset = path->path_length; struct buffer_head * bh; if (offset < FIRST_PATH_ELEMENT_OFFSET) die ("_get_rkey: illegal offset in the path (%d)", offset); while (offset-- > FIRST_PATH_ELEMENT_OFFSET) { if (! buffer_uptodate (PATH_OFFSET_PBUFFER (path, offset))) die ("_get_rkey: parent is not uptodate"); /* Parent at the path is not in the tree now. */ if (! B_IS_IN_TREE (bh = PATH_OFFSET_PBUFFER (path, offset))) die ("_get_rkey: buffer on the path is not in tree"); /* Check whether position in the parrent is correct. */ if ((pos = PATH_OFFSET_POSITION (path, offset)) > B_NR_ITEMS (bh)) die ("_get_rkey: invalid position (%d) in the path", pos); /* Check whether parent at the path really points to the child. */ if (B_N_CHILD_NUM (bh, pos) != PATH_OFFSET_PBUFFER (path, offset + 1)->b_blocknr) die ("_get_rkey: invalid block number (%d). Must be %d", B_N_CHILD_NUM (bh, pos), PATH_OFFSET_PBUFFER (path, offset + 1)->b_blocknr); /* Return delimiting key if position in the parent is not the last one. */ if (pos != B_NR_ITEMS (bh)) return B_N_PDELIM_KEY (bh, pos); } /* there is no right delimiting key */ return 0; }
int is_internal_bad (struct buffer_head * bh) { struct key * key; int i; if (!is_internal_node(bh)) return 0; for (i = 0; i < B_NR_ITEMS (bh); i ++) { key = B_N_PDELIM_KEY (bh, i); if (//key->k_dir_id >= key->k_objectid || le32_to_cpu(key->u.k_offset_v1.k_uniqueness) != V1_DIRENTRY_UNIQUENESS && le32_to_cpu(key->u.k_offset_v1.k_uniqueness) != V1_DIRECT_UNIQUENESS && le32_to_cpu(key->u.k_offset_v1.k_uniqueness) != V1_INDIRECT_UNIQUENESS && le32_to_cpu(key->u.k_offset_v1.k_uniqueness) != V1_SD_UNIQUENESS && offset_v2_k_type( &(key->u.k_offset_v2) ) != TYPE_DIRENTRY && offset_v2_k_type( &(key->u.k_offset_v2) ) != TYPE_DIRECT && offset_v2_k_type( &(key->u.k_offset_v2) ) != TYPE_INDIRECT && offset_v2_k_type( &(key->u.k_offset_v2) ) != TYPE_STAT_DATA //&& // key->u.k_offset_v1.k_uniqueness != V1_ANY_UNIQUENESS && key->u.k_offset_v2.k_type != TYPE_ANY ) return 1; } return 0; }
/* Replace delimiting key of buffers S[h] and R[h] by the given key.*/ static void replace_rkey(struct tree_balance *tb, int h, struct item_head *key) { RFALSE(tb->R[h] == NULL || tb->CFR[h] == NULL, "R[h](%p) and CFR[h](%p) must exist in replace_rkey", tb->R[h], tb->CFR[h]); RFALSE(B_NR_ITEMS(tb->R[h]) == 0, "R[h] can not be empty if it exists (item number=%d)", B_NR_ITEMS(tb->R[h])); memcpy(B_N_PDELIM_KEY(tb->CFR[h], tb->rkey[h]), key, KEY_SIZE); do_balance_mark_internal_dirty(tb, tb->CFR[h], 0); }
/* Replace delimiting key of buffers L[h] and S[h] by the given key.*/ static void replace_lkey(struct tree_balance *tb, int h, struct item_head *key) { RFALSE(tb->L[h] == NULL || tb->CFL[h] == NULL, "L[h](%p) and CFL[h](%p) must exist in replace_lkey", tb->L[h], tb->CFL[h]); if (B_NR_ITEMS(PATH_H_PBUFFER(tb->tb_path, h)) == 0) return; memcpy(B_N_PDELIM_KEY(tb->CFL[h], tb->lkey[h]), key, KEY_SIZE); do_balance_mark_internal_dirty(tb, tb->CFL[h], 0); }
static void reiserfsck_check_tree (int dev, int block, int size, check_function_t comp_func) { struct buffer_head * bh; int what_node; bh = bread (dev, block, size); if (bh == 0) reiserfs_panic("reiserfsck_check_tree: unable to read %lu block on device 0x%x\n", block, dev); if (!B_IS_IN_TREE (bh)) { reiserfs_panic (0, "reiserfsck_check_tree: buffer (%b %z) not in tree", bh, bh); } what_node = who_is_this (bh->b_data, bh->b_size); if (what_node != THE_LEAF && what_node != THE_INTERNAL) die ("Not formatted node"); if (!is_block_used (bh->b_blocknr)) die ("Not marked as used"); if (is_leaf_node (bh) && is_leaf_bad_xx (bh)) die ("Bad leaf"); if (is_internal_node(bh) && is_internal_bad (bh)) die ("bad internal"); if (is_internal_node (bh)) { int i; struct disk_child * dc; dc = B_N_CHILD (bh, 0); for (i = 0; i <= B_NR_ITEMS (bh); i ++, dc ++) { reiserfsck_check_tree (dev, dc_block_number(dc), size, comp_func); g_dkey = B_N_PDELIM_KEY (bh, i); } } else if (is_leaf_node (bh)) { g_right = bh; if (g_left != 0 && g_dkey != 0) { comp_func (); brelse (g_left); } g_left = g_right; return; } else { reiserfs_panic ("reiserfsck_check_tree: block %lu has bad block type (%b)", bh->b_blocknr, bh); } brelse (bh); }
/* Get delimiting key of the buffer at the path and its right neighbor. */ const struct key * get_rkey(const struct path *p_s_chk_path, const struct reiserfs_sb_info *p_s_sbi) { struct buf *p_s_parent; int n_position, n_path_offset = p_s_chk_path->path_length; while (n_path_offset-- > FIRST_PATH_ELEMENT_OFFSET) { /* Parent at the path is not in the tree now. */ if (!B_IS_IN_TREE(p_s_parent = PATH_OFFSET_PBUFFER(p_s_chk_path, n_path_offset))) return (&MIN_KEY); /* Check whether position in the parent is correct. */ if ((n_position = PATH_OFFSET_POSITION(p_s_chk_path, n_path_offset)) > B_NR_ITEMS(p_s_parent)) return (&MIN_KEY); /* * Check whether parent at the path really points to the * child. */ if (B_N_CHILD_NUM(p_s_parent, n_position) != (PATH_OFFSET_PBUFFER(p_s_chk_path, n_path_offset + 1)->b_blkno / btodb(p_s_sbi->s_blocksize))) return (&MIN_KEY); /* * Return delimiting key if position in the parent is not * the last one. */ if (n_position != B_NR_ITEMS(p_s_parent)) return (B_N_PDELIM_KEY(p_s_parent, n_position)); } /* Return MAX_KEY if we are in the root of the buffer tree. */ if ((PATH_OFFSET_PBUFFER(p_s_chk_path, FIRST_PATH_ELEMENT_OFFSET)->b_blkno / btodb(p_s_sbi->s_blocksize)) == SB_ROOT_BLOCK(p_s_sbi)) return (&MAX_KEY); return (&MIN_KEY); }
/* Get delimiting key of the buffer by looking for it in the buffers in the path, starting from the bottom of the path, and going upwards. We must check the path's validity at each step. If the key is not in the path, there is no delimiting key in the tree (buffer is first or last buffer in tree), and in this case we return a special key, either MIN_KEY or MAX_KEY. */ static inline const struct reiserfs_key *get_lkey(const struct treepath *chk_path, const struct super_block *sb) { int position, path_offset = chk_path->path_length; struct buffer_head *parent; RFALSE(path_offset < FIRST_PATH_ELEMENT_OFFSET, "PAP-5010: invalid offset in the path"); /* While not higher in path than first element. */ while (path_offset-- > FIRST_PATH_ELEMENT_OFFSET) { RFALSE(!buffer_uptodate (PATH_OFFSET_PBUFFER(chk_path, path_offset)), "PAP-5020: parent is not uptodate"); /* Parent at the path is not in the tree now. */ if (!B_IS_IN_TREE (parent = PATH_OFFSET_PBUFFER(chk_path, path_offset))) return &MAX_KEY; /* Check whether position in the parent is correct. */ if ((position = PATH_OFFSET_POSITION(chk_path, path_offset)) > B_NR_ITEMS(parent)) return &MAX_KEY; /* Check whether parent at the path really points to the child. */ if (B_N_CHILD_NUM(parent, position) != PATH_OFFSET_PBUFFER(chk_path, path_offset + 1)->b_blocknr) return &MAX_KEY; /* Return delimiting key if position in the parent is not equal to zero. */ if (position) return B_N_PDELIM_KEY(parent, position - 1); } /* Return MIN_KEY if we are in the root of the buffer tree. */ if (PATH_OFFSET_PBUFFER(chk_path, FIRST_PATH_ELEMENT_OFFSET)-> b_blocknr == SB_ROOT_BLOCK(sb)) return &MIN_KEY; return &MAX_KEY; }
static void reiserfsck_check_cached_tree (int dev, int block, int size) { struct buffer_head * bh; int what_node; bh = find_buffer(dev, block, size); if (bh == 0) return; if (!buffer_uptodate (bh)) { die ("reiserfsck_check_cached_tree: found notuptodate buffer"); } bh->b_count ++; if (!B_IS_IN_TREE (bh)) { die ("reiserfsck_check_cached_tree: buffer (%b %z) not in tree", bh, bh); } what_node = who_is_this (bh->b_data, bh->b_size); if ((what_node != THE_LEAF && what_node != THE_INTERNAL) || !is_block_used (bh->b_blocknr) || (is_leaf_node (bh) && is_leaf_bad (bh)) || (is_internal_node(bh) && is_internal_bad (bh))) die ("reiserfsck_check_cached_tree: bad node in the tree"); if (is_internal_node (bh)) { int i; struct disk_child * dc; dc = B_N_CHILD (bh, 0); for (i = 0; i <= B_NR_ITEMS (bh); i ++, dc ++) { reiserfsck_check_cached_tree (dev, dc_block_number(dc), size); g_dkey = B_N_PDELIM_KEY (bh, i); } } else if (is_leaf_node (bh)) { brelse (bh); return; } else { reiserfs_panic ("reiserfsck_check_cached_tree: block %lu has bad block type (%b)", bh->b_blocknr, bh); } brelse (bh); }
/* Get delimiting key of the buffer at the path and its right neighbor. */ inline struct key * get_rkey ( struct path * p_s_chk_path, struct super_block * p_s_sb ) { int n_position, n_path_offset = p_s_chk_path->path_length; struct buffer_head * p_s_parent; #ifdef CONFIG_REISERFS_CHECK if ( n_path_offset < FIRST_PATH_ELEMENT_OFFSET ) reiserfs_panic(p_s_sb,"PAP-5030: get_rkey: illegal offset in the path"); #endif while ( n_path_offset-- > FIRST_PATH_ELEMENT_OFFSET ) { #ifdef CONFIG_REISERFS_CHECK if ( ! buffer_uptodate(PATH_OFFSET_PBUFFER(p_s_chk_path, n_path_offset)) ) reiserfs_panic(p_s_sb, "PAP-5040: get_rkey: parent is not uptodate"); #endif /* Parent at the path is not in the tree now. */ if ( ! B_IS_IN_TREE(p_s_parent = PATH_OFFSET_PBUFFER(p_s_chk_path, n_path_offset)) ) return &MIN_KEY; /* Check whether position in the parrent is correct. */ if ( (n_position = PATH_OFFSET_POSITION(p_s_chk_path, n_path_offset)) > B_NR_ITEMS(p_s_parent) ) return &MIN_KEY; /* Check whether parent at the path really points to the child. */ if ( B_N_CHILD_NUM(p_s_parent, n_position) != PATH_OFFSET_PBUFFER(p_s_chk_path, n_path_offset + 1)->b_blocknr ) return &MIN_KEY; /* Return delimiting key if position in the parent is not the last one. */ if ( n_position != B_NR_ITEMS(p_s_parent) ) return B_N_PDELIM_KEY(p_s_parent, n_position); } /* Return MAX_KEY if we are in the root of the buffer tree. */ if ( PATH_OFFSET_PBUFFER(p_s_chk_path, FIRST_PATH_ELEMENT_OFFSET)->b_blocknr == SB_ROOT_BLOCK (p_s_sb) ) return &MAX_KEY; return &MIN_KEY; }
int balance_internal(struct tree_balance *tb, /* tree_balance structure */ int h, /* level of the tree */ int child_pos, struct item_head *insert_key, /* key for insertion on higher level */ struct buffer_head **insert_ptr /* node for insertion on higher level */ ) /* if inserting/pasting { child_pos is the position of the node-pointer in S[h] that * pointed to S[h-1] before balancing of the h-1 level; * this means that new pointers and items must be inserted AFTER * child_pos } else { it is the position of the leftmost pointer that must be deleted (together with its corresponding key to the left of the pointer) as a result of the previous level's balancing. } */ { struct buffer_head *tbSh = PATH_H_PBUFFER(tb->tb_path, h); struct buffer_info bi; int order; /* we return this: it is 0 if there is no S[h], else it is tb->S[h]->b_item_order */ int insert_num, n, k; struct buffer_head *S_new; struct item_head new_insert_key; struct buffer_head *new_insert_ptr = NULL; struct item_head *new_insert_key_addr = insert_key; RFALSE(h < 1, "h (%d) can not be < 1 on internal level", h); PROC_INFO_INC(tb->tb_sb, balance_at[h]); order = (tbSh) ? PATH_H_POSITION(tb->tb_path, h + 1) /*tb->S[h]->b_item_order */ : 0; /* Using insert_size[h] calculate the number insert_num of items that must be inserted to or deleted from S[h]. */ insert_num = tb->insert_size[h] / ((int)(KEY_SIZE + DC_SIZE)); /* Check whether insert_num is proper * */ RFALSE(insert_num < -2 || insert_num > 2, "incorrect number of items inserted to the internal node (%d)", insert_num); RFALSE(h > 1 && (insert_num > 1 || insert_num < -1), "incorrect number of items (%d) inserted to the internal node on a level (h=%d) higher than last internal level", insert_num, h); /* Make balance in case insert_num < 0 */ if (insert_num < 0) { balance_internal_when_delete(tb, h, child_pos); return order; } k = 0; if (tb->lnum[h] > 0) { /* shift lnum[h] items from S[h] to the left neighbor L[h]. check how many of new items fall into L[h] or CFL[h] after shifting */ n = B_NR_ITEMS(tb->L[h]); /* number of items in L[h] */ if (tb->lnum[h] <= child_pos) { /* new items don't fall into L[h] or CFL[h] */ internal_shift_left(INTERNAL_SHIFT_FROM_S_TO_L, tb, h, tb->lnum[h]); /*internal_shift_left (tb->L[h],tb->CFL[h],tb->lkey[h],tbSh,tb->lnum[h]); */ child_pos -= tb->lnum[h]; } else if (tb->lnum[h] > child_pos + insert_num) { /* all new items fall into L[h] */ internal_shift_left(INTERNAL_SHIFT_FROM_S_TO_L, tb, h, tb->lnum[h] - insert_num); /* internal_shift_left(tb->L[h],tb->CFL[h],tb->lkey[h],tbSh, tb->lnum[h]-insert_num); */ /* insert insert_num keys and node-pointers into L[h] */ bi.tb = tb; bi.bi_bh = tb->L[h]; bi.bi_parent = tb->FL[h]; bi.bi_position = get_left_neighbor_position(tb, h); internal_insert_childs(&bi, /*tb->L[h], tb->S[h-1]->b_next */ n + child_pos + 1, insert_num, insert_key, insert_ptr); insert_num = 0; } else { struct disk_child *dc; /* some items fall into L[h] or CFL[h], but some don't fall */ internal_shift1_left(tb, h, child_pos + 1); /* calculate number of new items that fall into L[h] */ k = tb->lnum[h] - child_pos - 1; bi.tb = tb; bi.bi_bh = tb->L[h]; bi.bi_parent = tb->FL[h]; bi.bi_position = get_left_neighbor_position(tb, h); internal_insert_childs(&bi, /*tb->L[h], tb->S[h-1]->b_next, */ n + child_pos + 1, k, insert_key, insert_ptr); replace_lkey(tb, h, insert_key + k); /* replace the first node-ptr in S[h] by node-ptr to insert_ptr[k] */ dc = B_N_CHILD(tbSh, 0); put_dc_size(dc, MAX_CHILD_SIZE(insert_ptr[k]) - B_FREE_SPACE(insert_ptr[k])); put_dc_block_number(dc, insert_ptr[k]->b_blocknr); do_balance_mark_internal_dirty(tb, tbSh, 0); k++; insert_key += k; insert_ptr += k; insert_num -= k; child_pos = 0; } } /* tb->lnum[h] > 0 */ if (tb->rnum[h] > 0) { /*shift rnum[h] items from S[h] to the right neighbor R[h] */ /* check how many of new items fall into R or CFR after shifting */ n = B_NR_ITEMS(tbSh); /* number of items in S[h] */ if (n - tb->rnum[h] >= child_pos) /* new items fall into S[h] */ /*internal_shift_right(tb,h,tbSh,tb->CFR[h],tb->rkey[h],tb->R[h],tb->rnum[h]); */ internal_shift_right(INTERNAL_SHIFT_FROM_S_TO_R, tb, h, tb->rnum[h]); else if (n + insert_num - tb->rnum[h] < child_pos) { /* all new items fall into R[h] */ /*internal_shift_right(tb,h,tbSh,tb->CFR[h],tb->rkey[h],tb->R[h], tb->rnum[h] - insert_num); */ internal_shift_right(INTERNAL_SHIFT_FROM_S_TO_R, tb, h, tb->rnum[h] - insert_num); /* insert insert_num keys and node-pointers into R[h] */ bi.tb = tb; bi.bi_bh = tb->R[h]; bi.bi_parent = tb->FR[h]; bi.bi_position = get_right_neighbor_position(tb, h); internal_insert_childs(&bi, /*tb->R[h],tb->S[h-1]->b_next */ child_pos - n - insert_num + tb->rnum[h] - 1, insert_num, insert_key, insert_ptr); insert_num = 0; } else { struct disk_child *dc; /* one of the items falls into CFR[h] */ internal_shift1_right(tb, h, n - child_pos + 1); /* calculate number of new items that fall into R[h] */ k = tb->rnum[h] - n + child_pos - 1; bi.tb = tb; bi.bi_bh = tb->R[h]; bi.bi_parent = tb->FR[h]; bi.bi_position = get_right_neighbor_position(tb, h); internal_insert_childs(&bi, /*tb->R[h], tb->R[h]->b_child, */ 0, k, insert_key + 1, insert_ptr + 1); replace_rkey(tb, h, insert_key + insert_num - k - 1); /* replace the first node-ptr in R[h] by node-ptr insert_ptr[insert_num-k-1] */ dc = B_N_CHILD(tb->R[h], 0); put_dc_size(dc, MAX_CHILD_SIZE(insert_ptr [insert_num - k - 1]) - B_FREE_SPACE(insert_ptr [insert_num - k - 1])); put_dc_block_number(dc, insert_ptr[insert_num - k - 1]->b_blocknr); do_balance_mark_internal_dirty(tb, tb->R[h], 0); insert_num -= (k + 1); } } /** Fill new node that appears instead of S[h] **/ RFALSE(tb->blknum[h] > 2, "blknum can not be > 2 for internal level"); RFALSE(tb->blknum[h] < 0, "blknum can not be < 0"); if (!tb->blknum[h]) { /* node S[h] is empty now */ RFALSE(!tbSh, "S[h] is equal NULL"); /* do what is needed for buffer thrown from tree */ reiserfs_invalidate_buffer(tb, tbSh); return order; } if (!tbSh) { /* create new root */ struct disk_child *dc; struct buffer_head *tbSh_1 = PATH_H_PBUFFER(tb->tb_path, h - 1); struct block_head *blkh; if (tb->blknum[h] != 1) reiserfs_panic(NULL, "ibalance-3", "One new node " "required for creating the new root"); /* S[h] = empty buffer from the list FEB. */ tbSh = get_FEB(tb); blkh = B_BLK_HEAD(tbSh); set_blkh_level(blkh, h + 1); /* Put the unique node-pointer to S[h] that points to S[h-1]. */ dc = B_N_CHILD(tbSh, 0); put_dc_block_number(dc, tbSh_1->b_blocknr); put_dc_size(dc, (MAX_CHILD_SIZE(tbSh_1) - B_FREE_SPACE(tbSh_1))); tb->insert_size[h] -= DC_SIZE; set_blkh_free_space(blkh, blkh_free_space(blkh) - DC_SIZE); do_balance_mark_internal_dirty(tb, tbSh, 0); /*&&&&&&&&&&&&&&&&&&&&&&&& */ check_internal(tbSh); /*&&&&&&&&&&&&&&&&&&&&&&&& */ /* put new root into path structure */ PATH_OFFSET_PBUFFER(tb->tb_path, ILLEGAL_PATH_ELEMENT_OFFSET) = tbSh; /* Change root in structure super block. */ PUT_SB_ROOT_BLOCK(tb->tb_sb, tbSh->b_blocknr); PUT_SB_TREE_HEIGHT(tb->tb_sb, SB_TREE_HEIGHT(tb->tb_sb) + 1); do_balance_mark_sb_dirty(tb, REISERFS_SB(tb->tb_sb)->s_sbh, 1); } if (tb->blknum[h] == 2) { int snum; struct buffer_info dest_bi, src_bi; /* S_new = free buffer from list FEB */ S_new = get_FEB(tb); set_blkh_level(B_BLK_HEAD(S_new), h + 1); dest_bi.tb = tb; dest_bi.bi_bh = S_new; dest_bi.bi_parent = NULL; dest_bi.bi_position = 0; src_bi.tb = tb; src_bi.bi_bh = tbSh; src_bi.bi_parent = PATH_H_PPARENT(tb->tb_path, h); src_bi.bi_position = PATH_H_POSITION(tb->tb_path, h + 1); n = B_NR_ITEMS(tbSh); /* number of items in S[h] */ snum = (insert_num + n + 1) / 2; if (n - snum >= child_pos) { /* new items don't fall into S_new */ /* store the delimiting key for the next level */ /* new_insert_key = (n - snum)'th key in S[h] */ memcpy(&new_insert_key, B_N_PDELIM_KEY(tbSh, n - snum), KEY_SIZE); /* last parameter is del_par */ internal_move_pointers_items(&dest_bi, &src_bi, LAST_TO_FIRST, snum, 0); /* internal_move_pointers_items(S_new, tbSh, LAST_TO_FIRST, snum, 0); */ } else if (n + insert_num - snum < child_pos) { /* all new items fall into S_new */ /* store the delimiting key for the next level */ /* new_insert_key = (n + insert_item - snum)'th key in S[h] */ memcpy(&new_insert_key, B_N_PDELIM_KEY(tbSh, n + insert_num - snum), KEY_SIZE); /* last parameter is del_par */ internal_move_pointers_items(&dest_bi, &src_bi, LAST_TO_FIRST, snum - insert_num, 0); /* internal_move_pointers_items(S_new,tbSh,1,snum - insert_num,0); */ /* insert insert_num keys and node-pointers into S_new */ internal_insert_childs(&dest_bi, /*S_new,tb->S[h-1]->b_next, */ child_pos - n - insert_num + snum - 1, insert_num, insert_key, insert_ptr); insert_num = 0; } else { struct disk_child *dc; /* some items fall into S_new, but some don't fall */ /* last parameter is del_par */ internal_move_pointers_items(&dest_bi, &src_bi, LAST_TO_FIRST, n - child_pos + 1, 1); /* internal_move_pointers_items(S_new,tbSh,1,n - child_pos + 1,1); */ /* calculate number of new items that fall into S_new */ k = snum - n + child_pos - 1; internal_insert_childs(&dest_bi, /*S_new, */ 0, k, insert_key + 1, insert_ptr + 1); /* new_insert_key = insert_key[insert_num - k - 1] */ memcpy(&new_insert_key, insert_key + insert_num - k - 1, KEY_SIZE); /* replace first node-ptr in S_new by node-ptr to insert_ptr[insert_num-k-1] */ dc = B_N_CHILD(S_new, 0); put_dc_size(dc, (MAX_CHILD_SIZE (insert_ptr[insert_num - k - 1]) - B_FREE_SPACE(insert_ptr [insert_num - k - 1]))); put_dc_block_number(dc, insert_ptr[insert_num - k - 1]->b_blocknr); do_balance_mark_internal_dirty(tb, S_new, 0); insert_num -= (k + 1); } /* new_insert_ptr = node_pointer to S_new */ new_insert_ptr = S_new; RFALSE(!buffer_journaled(S_new) || buffer_journal_dirty(S_new) || buffer_dirty(S_new), "cm-00001: bad S_new (%b)", S_new); // S_new is released in unfix_nodes } n = B_NR_ITEMS(tbSh); /*number of items in S[h] */ if (0 <= child_pos && child_pos <= n && insert_num > 0) { bi.tb = tb; bi.bi_bh = tbSh; bi.bi_parent = PATH_H_PPARENT(tb->tb_path, h); bi.bi_position = PATH_H_POSITION(tb->tb_path, h + 1); internal_insert_childs(&bi, /*tbSh, */ /* ( tb->S[h-1]->b_parent == tb->S[h] ) ? tb->S[h-1]->b_next : tb->S[h]->b_child->b_next, */ child_pos, insert_num, insert_key, insert_ptr); } memcpy(new_insert_key_addr, &new_insert_key, KEY_SIZE); insert_ptr[0] = new_insert_ptr; return order; }
/* copy cpy_num node pointers and cpy_num - 1 items from buffer src to buffer dest * last_first == FIRST_TO_LAST means, that we copy first items from src to tail of dest * last_first == LAST_TO_FIRST means, that we copy last items from src to head of dest */ static void internal_copy_pointers_items(struct buffer_info *dest_bi, struct buffer_head *src, int last_first, int cpy_num) { /* ATTENTION! Number of node pointers in DEST is equal to number of items in DEST * * as delimiting key have already inserted to buffer dest.*/ struct buffer_head *dest = dest_bi->bi_bh; int nr_dest, nr_src; int dest_order, src_order; struct block_head *blkh; struct reiserfs_key *key; struct disk_child *dc; nr_src = B_NR_ITEMS(src); RFALSE(dest == NULL || src == NULL, "src (%p) or dest (%p) buffer is 0", src, dest); RFALSE(last_first != FIRST_TO_LAST && last_first != LAST_TO_FIRST, "invalid last_first parameter (%d)", last_first); RFALSE(nr_src < cpy_num - 1, "no so many items (%d) in src (%d)", cpy_num, nr_src); RFALSE(cpy_num < 0, "cpy_num less than 0 (%d)", cpy_num); RFALSE(cpy_num - 1 + B_NR_ITEMS(dest) > (int)MAX_NR_KEY(dest), "cpy_num (%d) + item number in dest (%d) can not be > MAX_NR_KEY(%d)", cpy_num, B_NR_ITEMS(dest), MAX_NR_KEY(dest)); if (cpy_num == 0) return; /* coping */ blkh = B_BLK_HEAD(dest); nr_dest = blkh_nr_item(blkh); /*dest_order = (last_first == LAST_TO_FIRST) ? 0 : nr_dest; */ /*src_order = (last_first == LAST_TO_FIRST) ? (nr_src - cpy_num + 1) : 0; */ (last_first == LAST_TO_FIRST) ? (dest_order = 0, src_order = nr_src - cpy_num + 1) : (dest_order = nr_dest, src_order = 0); /* prepare space for cpy_num pointers */ dc = B_N_CHILD(dest, dest_order); memmove(dc + cpy_num, dc, (nr_dest - dest_order) * DC_SIZE); /* insert pointers */ memcpy(dc, B_N_CHILD(src, src_order), DC_SIZE * cpy_num); /* prepare space for cpy_num - 1 item headers */ key = B_N_PDELIM_KEY(dest, dest_order); memmove(key + cpy_num - 1, key, KEY_SIZE * (nr_dest - dest_order) + DC_SIZE * (nr_dest + cpy_num)); /* insert headers */ memcpy(key, B_N_PDELIM_KEY(src, src_order), KEY_SIZE * (cpy_num - 1)); /* sizes, item number */ set_blkh_nr_item(blkh, blkh_nr_item(blkh) + (cpy_num - 1)); set_blkh_free_space(blkh, blkh_free_space(blkh) - (KEY_SIZE * (cpy_num - 1) + DC_SIZE * cpy_num)); do_balance_mark_internal_dirty(dest_bi->tb, dest, 0); /*&&&&&&&&&&&&&&&&&&&&&&&& */ check_internal(dest); /*&&&&&&&&&&&&&&&&&&&&&&&& */ if (dest_bi->bi_parent) { struct disk_child *t_dc; t_dc = B_N_CHILD(dest_bi->bi_parent, dest_bi->bi_position); put_dc_size(t_dc, dc_size(t_dc) + (KEY_SIZE * (cpy_num - 1) + DC_SIZE * cpy_num)); do_balance_mark_internal_dirty(dest_bi->tb, dest_bi->bi_parent, 0); /*&&&&&&&&&&&&&&&&&&&&&&&& */ check_internal(dest_bi->bi_parent); /*&&&&&&&&&&&&&&&&&&&&&&&& */ } }
/* Delete del_num items and node pointers from buffer cur starting from * * the first_i'th item and first_p'th pointers respectively. */ static void internal_delete_pointers_items(struct buffer_info *cur_bi, int first_p, int first_i, int del_num) { struct buffer_head *cur = cur_bi->bi_bh; int nr; struct block_head *blkh; struct reiserfs_key *key; struct disk_child *dc; RFALSE(cur == NULL, "buffer is 0"); RFALSE(del_num < 0, "negative number of items (%d) can not be deleted", del_num); RFALSE(first_p < 0 || first_p + del_num > B_NR_ITEMS(cur) + 1 || first_i < 0, "first pointer order (%d) < 0 or " "no so many pointers (%d), only (%d) or " "first key order %d < 0", first_p, first_p + del_num, B_NR_ITEMS(cur) + 1, first_i); if (del_num == 0) return; blkh = B_BLK_HEAD(cur); nr = blkh_nr_item(blkh); if (first_p == 0 && del_num == nr + 1) { RFALSE(first_i != 0, "1st deleted key must have order 0, not %d", first_i); make_empty_node(cur_bi); return; } RFALSE(first_i + del_num > B_NR_ITEMS(cur), "first_i = %d del_num = %d " "no so many keys (%d) in the node (%b)(%z)", first_i, del_num, first_i + del_num, cur, cur); /* deleting */ dc = B_N_CHILD(cur, first_p); memmove(dc, dc + del_num, (nr + 1 - first_p - del_num) * DC_SIZE); key = B_N_PDELIM_KEY(cur, first_i); memmove(key, key + del_num, (nr - first_i - del_num) * KEY_SIZE + (nr + 1 - del_num) * DC_SIZE); /* sizes, item number */ set_blkh_nr_item(blkh, blkh_nr_item(blkh) - del_num); set_blkh_free_space(blkh, blkh_free_space(blkh) + (del_num * (KEY_SIZE + DC_SIZE))); do_balance_mark_internal_dirty(cur_bi->tb, cur, 0); /*&&&&&&&&&&&&&&&&&&&&&&& */ check_internal(cur); /*&&&&&&&&&&&&&&&&&&&&&&& */ if (cur_bi->bi_parent) { struct disk_child *t_dc; t_dc = B_N_CHILD(cur_bi->bi_parent, cur_bi->bi_position); put_dc_size(t_dc, dc_size(t_dc) - (del_num * (KEY_SIZE + DC_SIZE))); do_balance_mark_internal_dirty(cur_bi->tb, cur_bi->bi_parent, 0); /*&&&&&&&&&&&&&&&&&&&&&&&& */ check_internal(cur_bi->bi_parent); /*&&&&&&&&&&&&&&&&&&&&&&&& */ } }
/* Insert count node pointers into buffer cur before position to + 1. * Insert count items into buffer cur before position to. * Items and node pointers are specified by inserted and bh respectively. */ static void internal_insert_childs(struct buffer_info *cur_bi, int to, int count, struct item_head *inserted, struct buffer_head **bh) { struct buffer_head *cur = cur_bi->bi_bh; struct block_head *blkh; int nr; struct reiserfs_key *ih; struct disk_child new_dc[2]; struct disk_child *dc; int i; if (count <= 0) return; blkh = B_BLK_HEAD(cur); nr = blkh_nr_item(blkh); RFALSE(count > 2, "too many children (%d) are to be inserted", count); RFALSE(B_FREE_SPACE(cur) < count * (KEY_SIZE + DC_SIZE), "no enough free space (%d), needed %d bytes", B_FREE_SPACE(cur), count * (KEY_SIZE + DC_SIZE)); /* prepare space for count disk_child */ dc = B_N_CHILD(cur, to + 1); memmove(dc + count, dc, (nr + 1 - (to + 1)) * DC_SIZE); /* copy to_be_insert disk children */ for (i = 0; i < count; i++) { put_dc_size(&(new_dc[i]), MAX_CHILD_SIZE(bh[i]) - B_FREE_SPACE(bh[i])); put_dc_block_number(&(new_dc[i]), bh[i]->b_blocknr); } memcpy(dc, new_dc, DC_SIZE * count); /* prepare space for count items */ ih = B_N_PDELIM_KEY(cur, ((to == -1) ? 0 : to)); memmove(ih + count, ih, (nr - to) * KEY_SIZE + (nr + 1 + count) * DC_SIZE); /* copy item headers (keys) */ memcpy(ih, inserted, KEY_SIZE); if (count > 1) memcpy(ih + 1, inserted + 1, KEY_SIZE); /* sizes, item number */ set_blkh_nr_item(blkh, blkh_nr_item(blkh) + count); set_blkh_free_space(blkh, blkh_free_space(blkh) - count * (DC_SIZE + KEY_SIZE)); do_balance_mark_internal_dirty(cur_bi->tb, cur, 0); /*&&&&&&&&&&&&&&&&&&&&&&&& */ check_internal(cur); /*&&&&&&&&&&&&&&&&&&&&&&&& */ if (cur_bi->bi_parent) { struct disk_child *t_dc = B_N_CHILD(cur_bi->bi_parent, cur_bi->bi_position); put_dc_size(t_dc, dc_size(t_dc) + (count * (DC_SIZE + KEY_SIZE))); do_balance_mark_internal_dirty(cur_bi->tb, cur_bi->bi_parent, 0); /*&&&&&&&&&&&&&&&&&&&&&&&& */ check_internal(cur_bi->bi_parent); /*&&&&&&&&&&&&&&&&&&&&&&&& */ } }