This is the first in a set of 4 patches that split balance_leaf up into a group of functions rather than the 2500 beast it once was. This patch splits off the left-tree balancing behavior. Signed-off-by: Jeff Mahoney <jeffm@xxxxxxxx> --- fs/reiserfs/do_balan.c | 733 ++++++++++++++++++++----------------------------- 1 file changed, 313 insertions(+), 420 deletions(-) --- a/fs/reiserfs/do_balan.c 2007-06-11 14:49:41.000000000 -0400 +++ b/fs/reiserfs/do_balan.c 2007-06-11 14:50:01.000000000 -0400 @@ -276,6 +276,317 @@ static int balance_leaf_when_delete(stru return 0; } +/* Insert item into L[0] */ +static void +bl_left_insert(struct tree_balance *tb, struct item_head *ih, + const char *body, int flag, int *zeros_num) +{ + int shift = 0; + int was_copied; + int new_item_len; + struct buffer_info bi; + int n = B_NR_ITEMS(tb->L[0]); + int item_pos = PATH_LAST_POSITION(tb->tb_path); + + /* new item in whole falls into L[0] */ + if (item_pos != tb->lnum[0] - 1 || tb->lbytes == -1) { + /* Shift lnum[0]-1 items to L[0] */ + was_copied = leaf_shift_left(tb, tb->lnum[0] - 1, tb->lbytes); + /* Insert new item into L[0] */ + buffer_info_init_left(tb, &bi); + leaf_insert_into_buf(&bi, n + item_pos - was_copied, ih, body, + *zeros_num); + tb->insert_size[0] = 0; + *zeros_num = 0; + return; + } + + /* Only part of new item falls into L[0] */ + was_copied = leaf_shift_left(tb, tb->lnum[0] - 1, -1); + + /* Calculate item length to insert to S[0] */ + new_item_len = ih_item_len(ih) - tb->lbytes; + /* Calculate and check item length to insert to L[0] */ + put_ih_item_len(ih, ih_item_len(ih) - new_item_len); + + RFALSE(ih_item_len(ih) <= 0, "PAP-12080: there is nothing to " + "insert into L[0]: ih_item_len=%d", ih_item_len(ih)); + + /* Insert new item into L[0] */ + buffer_info_init_left(tb, &bi); + leaf_insert_into_buf(&bi, n + item_pos - was_copied, ih, body, + *zeros_num > ih_item_len(ih) ? ih_item_len(ih) : + *zeros_num); + + /* Calculate key component, item length and body to insert into S[0] */ + if (is_indirect_le_ih(ih)) + shift = tb->tb_sb->s_blocksize_bits - UNFM_P_SHIFT; + set_le_ih_k_offset(ih, le_ih_k_offset(ih) + (tb->lbytes << shift)); + + put_ih_item_len(ih, new_item_len); + if (tb->lbytes > *zeros_num) { + body += (tb->lbytes - *zeros_num); + *zeros_num = 0; + } else + *zeros_num -= tb->lbytes; + + RFALSE(ih_item_len(ih) <= 0, "PAP-12085: there is nothing to " + "insert into S[0]: ih_item_len=%d", ih_item_len(ih)); +} + +/* directory item */ +static void +bl_left_paste_de_partial(struct tree_balance *tb, struct item_head *ih, + const char *body, int flag, int *zeros_num, + int *pos_in_item) +{ + struct item_head *pasted; + int l_pos_in_item = *pos_in_item; + int was_copied; + int item_pos = PATH_LAST_POSITION(tb->tb_path); + struct buffer_info bi; + int n = B_NR_ITEMS(tb->L[0]); + + RFALSE(*zeros_num, "PAP-12090: invalid parameter " + "in case of a directory"); + + if (tb->lbytes <= *pos_in_item) { + /* new directory item doesn't fall into L[0] */ + /* Shift lnum[0]-1 items in whole. Shift lbytes + * directory entries from directory item number + * lnum[0] */ + leaf_shift_left(tb, tb->lnum[0], tb->lbytes); + /* Calculate new position to append in item body */ + *pos_in_item -= tb->lbytes; + return; + } + + /* new directory entry falls into L[0] */ + + /* Shift lnum[0] - 1 items in whole. + * Shift lbytes - 1 entries from given directory item */ + was_copied = leaf_shift_left(tb, tb->lnum[0], tb->lbytes - 1); + if (was_copied && !item_pos) { + pasted = B_N_PITEM_HEAD(tb->L[0], B_NR_ITEMS(tb->L[0]) - 1); + l_pos_in_item += I_ENTRY_COUNT(pasted) - (tb->lbytes - 1); + } + + /* Append given directory entry to directory item */ + buffer_info_init_left(tb, &bi); + leaf_paste_in_buffer(&bi, n + item_pos - was_copied, l_pos_in_item, + tb->insert_size[0], body, *zeros_num); + + /* previous string prepared space for pasting new + * entry, following string pastes this entry */ + + /* when we have merge directory item, pos_in_item + * has been changed too */ + + /* paste new directory entry. 1 is entry number */ + leaf_paste_entries(bi.bi_bh, + n + item_pos - was_copied, + l_pos_in_item, 1, + (struct reiserfs_de_head *) body, + body + DEH_SIZE, tb->insert_size[0]); + tb->insert_size[0] = 0; + + /* Calculate new position to append in item body */ + *pos_in_item -= tb->lbytes; +} + +static void +bl_left_paste_non_de_partial(struct tree_balance *tb, struct item_head *ih, + const char *body, int flag, int *zeros_num, + int *pos_in_item) +{ + struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path); + int item_pos = PATH_LAST_POSITION(tb->tb_path); + struct buffer_info bi; + int l_n, version, temp_l; + u64 offset; + int was_copied; + int n = B_NR_ITEMS(tb->L[0]); + + /* regular object */ + RFALSE(tb->lbytes <= 0, "PAP-12095: there is nothing to " + "shift to L[0]. lbytes=%d", tb->lbytes); + RFALSE(*pos_in_item != ih_item_len(B_N_PITEM_HEAD(tbS0, item_pos)), + "PAP-12100: incorrect position to paste: " + "item_len=%d, pos_in_item=%d", + ih_item_len(B_N_PITEM_HEAD(tbS0, item_pos)), *pos_in_item); + + /* only part of the appended item will be in L[0] */ + if (tb->lbytes < *pos_in_item) { + /* Calculate position in item for append in S[0] */ + *pos_in_item -= tb->lbytes; + + RFALSE(*pos_in_item <= 0, + "PAP-12125: no place for paste. pos_in_item=%d", + *pos_in_item); + + /* Shift lnum[0] - 1 items in whole. + * Shift lbytes - 1 byte from item number lnum[0] */ + leaf_shift_left(tb, tb->lnum[0], tb->lbytes); + return; + } + + /* appended item will be in L[0] in whole */ + /* this bytes number must be appended to the last item of L[h] */ + l_n = tb->lbytes - *pos_in_item; + + /* Calculate new insert_size[0] */ + tb->insert_size[0] -= l_n; + + RFALSE(tb-> insert_size[0] <= 0, "PAP-12105: there is " + "nothing to paste into L[0]. insert_size=%d", + tb->insert_size[0]); + was_copied = leaf_shift_left(tb, tb->lnum[0], + ih_item_len(B_N_PITEM_HEAD(tbS0, item_pos))); + /* Append to body of item in L[0] */ + buffer_info_init_left(tb, &bi); + leaf_paste_in_buffer(&bi, n + item_pos - was_copied, + ih_item_len(B_N_PITEM_HEAD(tb->L[0], + n + item_pos - + was_copied)), + l_n, body, + *zeros_num > l_n ? l_n : *zeros_num); + /* 0-th item in S0 can be only of DIRECT type when l_n != 0 */ + temp_l = l_n; + RFALSE(ih_item_len (B_N_PITEM_HEAD(tbS0, 0)), + "PAP-12106: item length must be 0"); + RFALSE(comp_short_le_keys(B_N_PKEY(tbS0, 0), + B_N_PKEY(tb->L[0], n + item_pos - was_copied)), + "PAP-12107: items must be of the same file"); + if (is_indirect_le_ih(B_N_PITEM_HEAD(tb->L[0], + n + item_pos - was_copied))) { + temp_l = l_n << (tb->tb_sb-> s_blocksize_bits - UNFM_P_SHIFT); + } + /* update key of first item in S0 */ + version = ih_version(B_N_PITEM_HEAD(tbS0, 0)); + set_le_key_k_offset(version, B_N_PKEY(tbS0, 0), + le_key_k_offset(version, B_N_PKEY(tbS0, 0)) + + temp_l); + /* update left delimiting key */ + offset = le_key_k_offset(version, + B_N_PDELIM_KEY(tb->CFL[0], tb->lkey[0])) + temp_l; + set_le_key_k_offset(version, B_N_PDELIM_KEY(tb->CFL[0], tb->lkey[0]), + offset); + + /* Calculate new body, position in item + * and insert_size[0] */ + if (l_n > *zeros_num) { + body += (l_n - *zeros_num); + *zeros_num = 0; + } else + *zeros_num -= l_n; + + *pos_in_item = 0; + + RFALSE(comp_short_le_keys(B_N_PKEY(tbS0, 0), + B_N_PKEY(tb->L[0], B_NR_ITEMS(tb->L[0]) - 1)) + || !op_is_left_mergeable(B_N_PKEY(tbS0, 0), tbS0->b_size) + || !op_is_left_mergeable(B_N_PDELIM_KEY (tb->CFL[0], + tb->lkey[0]), tbS0->b_size), + "PAP-12120: item must be merge-able with left neighboring item"); +} + +static void +bl_left_paste_solid(struct tree_balance *tb, struct item_head *ih, + const char *body, int flag, int *zeros_num, + int *pos_in_item) +{ + int was_copied; + int item_pos = PATH_LAST_POSITION(tb->tb_path); + int n = B_NR_ITEMS(tb->L[0]); + struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path); + struct buffer_info bi; + struct item_head *pasted; + + /* appended item will be in L[0] in whole */ + if (!item_pos && + op_is_left_mergeable(B_N_PKEY(tbS0, 0), tbS0->b_size)) { + /* if we paste into first item of S[0] and it is + * left mergable */ + /* then increment pos_in_item by the size of the + * last item in L[0] */ + pasted = B_N_PITEM_HEAD(tb->L[0], n - 1); + if (is_direntry_le_ih(pasted)) + *pos_in_item += ih_entry_count(pasted); + else + *pos_in_item += ih_item_len(pasted); + } + + /* Shift lnum[0] - 1 items in whole. Shift lbytes - 1 byte + * from item number lnum[0] */ + was_copied = leaf_shift_left(tb, tb->lnum[0], tb->lbytes); + + /* Append to body of item in L[0] */ + buffer_info_init_left(tb, &bi); + leaf_paste_in_buffer(&bi, n + item_pos - was_copied, + *pos_in_item, tb->insert_size[0], body, + *zeros_num); + + /* if appended item is directory, paste entry */ + pasted = B_N_PITEM_HEAD(tb->L[0], n + item_pos - was_copied); + if (is_direntry_le_ih(pasted)) + leaf_paste_entries(bi.bi_bh, n + item_pos - was_copied, + *pos_in_item, 1, + (struct reiserfs_de_head *)body, + body + DEH_SIZE, tb->insert_size[0]); + /* if appended item is indirect item, put + * unformatted node into un list */ + if (is_indirect_le_ih(pasted)) + set_ih_free_space(pasted, 0); + tb->insert_size[0] = 0; + *zeros_num = 0; +} + +/* Append item in L[0] */ +static void +bl_left_paste(struct tree_balance *tb, struct item_head *ih, + const char *body, int flag, int *zeros_num, + int *pos_in_item) +{ + int item_pos = PATH_LAST_POSITION(tb->tb_path); + struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path); + + /* We must shift the part of the appended item */ + if (item_pos == tb->lnum[0] - 1 && tb->lbytes != -1) { + if (is_direntry_le_ih(B_N_PITEM_HEAD(tbS0, item_pos))) + bl_left_paste_de_partial(tb, ih, body, flag, zeros_num, + pos_in_item); + else + bl_left_paste_non_de_partial(tb, ih, body, flag, + zeros_num, pos_in_item); + return; + } else { + bl_left_paste_solid(tb, ih, body, flag, zeros_num, pos_in_item); + } +} + +/* Shift lnum[0] items from S[0] to the left neighbor L[0] */ +static void +bl_left(struct tree_balance *tb, struct item_head *ih, + const char *body, int flag, int *zeros_num, int *pos_in_item) +{ + int item_pos = PATH_LAST_POSITION(tb->tb_path); + + BUG_ON(flag != M_INSERT && flag != M_PASTE); + + /* new item doesn't fall into L[0] */ + if (item_pos >= tb->lnum[0]) { + leaf_shift_left(tb, tb->lnum[0], tb->lbytes); + return; + } + + /* new item or it part falls to L[0], shift it too */ + if (flag == M_INSERT) + bl_left_insert(tb, ih, body, flag, zeros_num); + else /* M_PASTE */ + bl_left_paste(tb, ih, body, flag, zeros_num, + pos_in_item); +} + static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item header of inserted item (this is on little endian) */ const char *body, /* body of inserted item or bytes to paste */ int flag, /* i - insert, d - delete, c - cut, p - paste @@ -314,426 +625,8 @@ static int balance_leaf(struct tree_bala && is_indirect_le_ih(B_N_PITEM_HEAD(tbS0, item_pos))) pos_in_item *= UNFM_P_SIZE; - if (tb->lnum[0] > 0) { - /* Shift lnum[0] items from S[0] to the left neighbor L[0] */ - if (item_pos < tb->lnum[0]) { - /* new item or it part falls to L[0], shift it too */ - n = B_NR_ITEMS(tb->L[0]); - - switch (flag) { - case M_INSERT: /* insert item into L[0] */ - - if (item_pos == tb->lnum[0] - 1 - && tb->lbytes != -1) { - /* part of new item falls into L[0] */ - int new_item_len; - int version; - - ret_val = - leaf_shift_left(tb, tb->lnum[0] - 1, - -1); - - /* Calculate item length to insert to S[0] */ - new_item_len = - ih_item_len(ih) - tb->lbytes; - /* Calculate and check item length to insert to L[0] */ - put_ih_item_len(ih, - ih_item_len(ih) - - new_item_len); - - RFALSE(ih_item_len(ih) <= 0, - "PAP-12080: there is nothing to insert into L[0]: ih_item_len=%d", - ih_item_len(ih)); - - /* Insert new item into L[0] */ - buffer_info_init_left(tb, &bi); - leaf_insert_into_buf(&bi, - n + item_pos - - ret_val, ih, body, - zeros_num > - ih_item_len(ih) ? - ih_item_len(ih) : - zeros_num); - - version = ih_version(ih); - - /* Calculate key component, item length and body to insert into S[0] */ - set_le_ih_k_offset(ih, - le_ih_k_offset(ih) + - (tb-> - lbytes << - (is_indirect_le_ih - (ih) ? tb->tb_sb-> - s_blocksize_bits - - UNFM_P_SHIFT : - 0))); - - put_ih_item_len(ih, new_item_len); - if (tb->lbytes > zeros_num) { - body += - (tb->lbytes - zeros_num); - zeros_num = 0; - } else - zeros_num -= tb->lbytes; - - RFALSE(ih_item_len(ih) <= 0, - "PAP-12085: there is nothing to insert into S[0]: ih_item_len=%d", - ih_item_len(ih)); - } else { - /* new item in whole falls into L[0] */ - /* Shift lnum[0]-1 items to L[0] */ - ret_val = - leaf_shift_left(tb, tb->lnum[0] - 1, - tb->lbytes); - /* Insert new item into L[0] */ - buffer_info_init_left(tb, &bi); - leaf_insert_into_buf(&bi, - n + item_pos - - ret_val, ih, body, - zeros_num); - tb->insert_size[0] = 0; - zeros_num = 0; - } - break; - - case M_PASTE: /* append item in L[0] */ - - if (item_pos == tb->lnum[0] - 1 - && tb->lbytes != -1) { - /* we must shift the part of the appended item */ - if (is_direntry_le_ih - (B_N_PITEM_HEAD(tbS0, item_pos))) { - - RFALSE(zeros_num, - "PAP-12090: invalid parameter in case of a directory"); - /* directory item */ - if (tb->lbytes > pos_in_item) { - /* new directory entry falls into L[0] */ - struct item_head - *pasted; - int l_pos_in_item = - pos_in_item; - - /* Shift lnum[0] - 1 items in whole. Shift lbytes - 1 entries from given directory item */ - ret_val = - leaf_shift_left(tb, - tb-> - lnum - [0], - tb-> - lbytes - - - 1); - if (ret_val - && !item_pos) { - pasted = - B_N_PITEM_HEAD - (tb->L[0], - B_NR_ITEMS - (tb-> - L[0]) - - 1); - l_pos_in_item += - I_ENTRY_COUNT - (pasted) - - (tb-> - lbytes - - 1); - } - - /* Append given directory entry to directory item */ - buffer_info_init_left(tb, &bi); - leaf_paste_in_buffer - (&bi, - n + item_pos - - ret_val, - l_pos_in_item, - tb->insert_size[0], - body, zeros_num); - - /* previous string prepared space for pasting new entry, following string pastes this entry */ - - /* when we have merge directory item, pos_in_item has been changed too */ - - /* paste new directory entry. 1 is entry number */ - leaf_paste_entries(bi. - bi_bh, - n + - item_pos - - - ret_val, - l_pos_in_item, - 1, - (struct - reiserfs_de_head - *) - body, - body - + - DEH_SIZE, - tb-> - insert_size - [0] - ); - tb->insert_size[0] = 0; - } else { - /* new directory item doesn't fall into L[0] */ - /* Shift lnum[0]-1 items in whole. Shift lbytes directory entries from directory item number lnum[0] */ - leaf_shift_left(tb, - tb-> - lnum[0], - tb-> - lbytes); - } - /* Calculate new position to append in item body */ - pos_in_item -= tb->lbytes; - } else { - /* regular object */ - RFALSE(tb->lbytes <= 0, - "PAP-12095: there is nothing to shift to L[0]. lbytes=%d", - tb->lbytes); - RFALSE(pos_in_item != - ih_item_len - (B_N_PITEM_HEAD - (tbS0, item_pos)), - "PAP-12100: incorrect position to paste: item_len=%d, pos_in_item=%d", - ih_item_len - (B_N_PITEM_HEAD - (tbS0, item_pos)), - pos_in_item); - - if (tb->lbytes >= pos_in_item) { - /* appended item will be in L[0] in whole */ - int l_n; - - /* this bytes number must be appended to the last item of L[h] */ - l_n = - tb->lbytes - - pos_in_item; - - /* Calculate new insert_size[0] */ - tb->insert_size[0] -= - l_n; - - RFALSE(tb-> - insert_size[0] <= - 0, - "PAP-12105: there is nothing to paste into L[0]. insert_size=%d", - tb-> - insert_size[0]); - ret_val = - leaf_shift_left(tb, - tb-> - lnum - [0], - ih_item_len - (B_N_PITEM_HEAD - (tbS0, - item_pos))); - /* Append to body of item in L[0] */ - buffer_info_init_left(tb, &bi); - leaf_paste_in_buffer - (&bi, - n + item_pos - - ret_val, - ih_item_len - (B_N_PITEM_HEAD - (tb->L[0], - n + item_pos - - ret_val)), l_n, - body, - zeros_num > - l_n ? l_n : - zeros_num); - /* 0-th item in S0 can be only of DIRECT type when l_n != 0 */ - { - int version; - int temp_l = - l_n; - - RFALSE - (ih_item_len - (B_N_PITEM_HEAD - (tbS0, - 0)), - "PAP-12106: item length must be 0"); - RFALSE - (comp_short_le_keys - (B_N_PKEY - (tbS0, 0), - B_N_PKEY - (tb->L[0], - n + - item_pos - - - ret_val)), - "PAP-12107: items must be of the same file"); - if (is_indirect_le_ih(B_N_PITEM_HEAD(tb->L[0], n + item_pos - ret_val))) { - temp_l = - l_n - << - (tb-> - tb_sb-> - s_blocksize_bits - - - UNFM_P_SHIFT); - } - /* update key of first item in S0 */ - version = - ih_version - (B_N_PITEM_HEAD - (tbS0, 0)); - set_le_key_k_offset - (version, - B_N_PKEY - (tbS0, 0), - le_key_k_offset - (version, - B_N_PKEY - (tbS0, - 0)) + - temp_l); - /* update left delimiting key */ - set_le_key_k_offset - (version, - B_N_PDELIM_KEY - (tb-> - CFL[0], - tb-> - lkey[0]), - le_key_k_offset - (version, - B_N_PDELIM_KEY - (tb-> - CFL[0], - tb-> - lkey[0])) - + temp_l); - } - - /* Calculate new body, position in item and insert_size[0] */ - if (l_n > zeros_num) { - body += - (l_n - - zeros_num); - zeros_num = 0; - } else - zeros_num -= - l_n; - pos_in_item = 0; - - RFALSE - (comp_short_le_keys - (B_N_PKEY(tbS0, 0), - B_N_PKEY(tb->L[0], - B_NR_ITEMS - (tb-> - L[0]) - - 1)) - || - !op_is_left_mergeable - (B_N_PKEY(tbS0, 0), - tbS0->b_size) - || - !op_is_left_mergeable - (B_N_PDELIM_KEY - (tb->CFL[0], - tb->lkey[0]), - tbS0->b_size), - "PAP-12120: item must be merge-able with left neighboring item"); - } else { /* only part of the appended item will be in L[0] */ - - /* Calculate position in item for append in S[0] */ - pos_in_item -= - tb->lbytes; - - RFALSE(pos_in_item <= 0, - "PAP-12125: no place for paste. pos_in_item=%d", - pos_in_item); - - /* Shift lnum[0] - 1 items in whole. Shift lbytes - 1 byte from item number lnum[0] */ - leaf_shift_left(tb, - tb-> - lnum[0], - tb-> - lbytes); - } - } - } else { /* appended item will be in L[0] in whole */ - - struct item_head *pasted; - - if (!item_pos && op_is_left_mergeable(B_N_PKEY(tbS0, 0), tbS0->b_size)) { /* if we paste into first item of S[0] and it is left mergable */ - /* then increment pos_in_item by the size of the last item in L[0] */ - pasted = - B_N_PITEM_HEAD(tb->L[0], - n - 1); - if (is_direntry_le_ih(pasted)) - pos_in_item += - ih_entry_count - (pasted); - else - pos_in_item += - ih_item_len(pasted); - } - - /* Shift lnum[0] - 1 items in whole. Shift lbytes - 1 byte from item number lnum[0] */ - ret_val = - leaf_shift_left(tb, tb->lnum[0], - tb->lbytes); - /* Append to body of item in L[0] */ - buffer_info_init_left(tb, &bi); - leaf_paste_in_buffer(&bi, - n + item_pos - - ret_val, - pos_in_item, - tb->insert_size[0], - body, zeros_num); - - /* if appended item is directory, paste entry */ - pasted = - B_N_PITEM_HEAD(tb->L[0], - n + item_pos - - ret_val); - if (is_direntry_le_ih(pasted)) - leaf_paste_entries(bi.bi_bh, - n + - item_pos - - ret_val, - pos_in_item, - 1, - (struct - reiserfs_de_head - *)body, - body + - DEH_SIZE, - tb-> - insert_size - [0] - ); - /* if appended item is indirect item, put unformatted node into un list */ - if (is_indirect_le_ih(pasted)) - set_ih_free_space(pasted, 0); - tb->insert_size[0] = 0; - zeros_num = 0; - } - break; - default: /* cases d and t */ - reiserfs_panic(tb->tb_sb, "PAP-12130", - "lnum > 0: unexpected mode: %s(%d)", - (flag == - M_DELETE) ? "DELETE" : ((flag == - M_CUT) - ? "CUT" - : - "UNKNOWN"), - flag); - } - } else { - /* new item doesn't fall into L[0] */ - leaf_shift_left(tb, tb->lnum[0], tb->lbytes); - } - } + if (tb->lnum[0] > 0) + bl_left(tb, ih, body, flag, &zeros_num, &pos_in_item); /* tb->lnum[0] > 0 */ /* Calculate new item position */ -- Jeff Mahoney SUSE Labs - To unsubscribe from this list: send the line "unsubscribe reiserfs-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html