18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
38c2ecf20Sopenharmony_ci */
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci/*
68c2ecf20Sopenharmony_ci * Now we have all buffers that must be used in balancing of the tree
78c2ecf20Sopenharmony_ci * Further calculations can not cause schedule(), and thus the buffer
88c2ecf20Sopenharmony_ci * tree will be stable until the balancing will be finished
98c2ecf20Sopenharmony_ci * balance the tree according to the analysis made before,
108c2ecf20Sopenharmony_ci * and using buffers obtained after all above.
118c2ecf20Sopenharmony_ci */
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#include <linux/uaccess.h>
148c2ecf20Sopenharmony_ci#include <linux/time.h>
158c2ecf20Sopenharmony_ci#include "reiserfs.h"
168c2ecf20Sopenharmony_ci#include <linux/buffer_head.h>
178c2ecf20Sopenharmony_ci#include <linux/kernel.h>
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_cistatic inline void buffer_info_init_left(struct tree_balance *tb,
208c2ecf20Sopenharmony_ci                                         struct buffer_info *bi)
218c2ecf20Sopenharmony_ci{
228c2ecf20Sopenharmony_ci	bi->tb          = tb;
238c2ecf20Sopenharmony_ci	bi->bi_bh       = tb->L[0];
248c2ecf20Sopenharmony_ci	bi->bi_parent   = tb->FL[0];
258c2ecf20Sopenharmony_ci	bi->bi_position = get_left_neighbor_position(tb, 0);
268c2ecf20Sopenharmony_ci}
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_cistatic inline void buffer_info_init_right(struct tree_balance *tb,
298c2ecf20Sopenharmony_ci                                          struct buffer_info *bi)
308c2ecf20Sopenharmony_ci{
318c2ecf20Sopenharmony_ci	bi->tb          = tb;
328c2ecf20Sopenharmony_ci	bi->bi_bh       = tb->R[0];
338c2ecf20Sopenharmony_ci	bi->bi_parent   = tb->FR[0];
348c2ecf20Sopenharmony_ci	bi->bi_position = get_right_neighbor_position(tb, 0);
358c2ecf20Sopenharmony_ci}
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_cistatic inline void buffer_info_init_tbS0(struct tree_balance *tb,
388c2ecf20Sopenharmony_ci                                         struct buffer_info *bi)
398c2ecf20Sopenharmony_ci{
408c2ecf20Sopenharmony_ci	bi->tb          = tb;
418c2ecf20Sopenharmony_ci	bi->bi_bh        = PATH_PLAST_BUFFER(tb->tb_path);
428c2ecf20Sopenharmony_ci	bi->bi_parent   = PATH_H_PPARENT(tb->tb_path, 0);
438c2ecf20Sopenharmony_ci	bi->bi_position = PATH_H_POSITION(tb->tb_path, 1);
448c2ecf20Sopenharmony_ci}
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_cistatic inline void buffer_info_init_bh(struct tree_balance *tb,
478c2ecf20Sopenharmony_ci                                       struct buffer_info *bi,
488c2ecf20Sopenharmony_ci                                       struct buffer_head *bh)
498c2ecf20Sopenharmony_ci{
508c2ecf20Sopenharmony_ci	bi->tb          = tb;
518c2ecf20Sopenharmony_ci	bi->bi_bh       = bh;
528c2ecf20Sopenharmony_ci	bi->bi_parent   = NULL;
538c2ecf20Sopenharmony_ci	bi->bi_position = 0;
548c2ecf20Sopenharmony_ci}
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ciinline void do_balance_mark_leaf_dirty(struct tree_balance *tb,
578c2ecf20Sopenharmony_ci				       struct buffer_head *bh, int flag)
588c2ecf20Sopenharmony_ci{
598c2ecf20Sopenharmony_ci	journal_mark_dirty(tb->transaction_handle, bh);
608c2ecf20Sopenharmony_ci}
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci#define do_balance_mark_internal_dirty do_balance_mark_leaf_dirty
638c2ecf20Sopenharmony_ci#define do_balance_mark_sb_dirty do_balance_mark_leaf_dirty
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci/*
668c2ecf20Sopenharmony_ci * summary:
678c2ecf20Sopenharmony_ci *  if deleting something ( tb->insert_size[0] < 0 )
688c2ecf20Sopenharmony_ci *    return(balance_leaf_when_delete()); (flag d handled here)
698c2ecf20Sopenharmony_ci *  else
708c2ecf20Sopenharmony_ci *    if lnum is larger than 0 we put items into the left node
718c2ecf20Sopenharmony_ci *    if rnum is larger than 0 we put items into the right node
728c2ecf20Sopenharmony_ci *    if snum1 is larger than 0 we put items into the new node s1
738c2ecf20Sopenharmony_ci *    if snum2 is larger than 0 we put items into the new node s2
748c2ecf20Sopenharmony_ci * Note that all *num* count new items being created.
758c2ecf20Sopenharmony_ci */
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_cistatic void balance_leaf_when_delete_del(struct tree_balance *tb)
788c2ecf20Sopenharmony_ci{
798c2ecf20Sopenharmony_ci	struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path);
808c2ecf20Sopenharmony_ci	int item_pos = PATH_LAST_POSITION(tb->tb_path);
818c2ecf20Sopenharmony_ci	struct buffer_info bi;
828c2ecf20Sopenharmony_ci#ifdef CONFIG_REISERFS_CHECK
838c2ecf20Sopenharmony_ci	struct item_head *ih = item_head(tbS0, item_pos);
848c2ecf20Sopenharmony_ci#endif
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci	RFALSE(ih_item_len(ih) + IH_SIZE != -tb->insert_size[0],
878c2ecf20Sopenharmony_ci	       "vs-12013: mode Delete, insert size %d, ih to be deleted %h",
888c2ecf20Sopenharmony_ci	       -tb->insert_size[0], ih);
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci	buffer_info_init_tbS0(tb, &bi);
918c2ecf20Sopenharmony_ci	leaf_delete_items(&bi, 0, item_pos, 1, -1);
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci	if (!item_pos && tb->CFL[0]) {
948c2ecf20Sopenharmony_ci		if (B_NR_ITEMS(tbS0)) {
958c2ecf20Sopenharmony_ci			replace_key(tb, tb->CFL[0], tb->lkey[0], tbS0, 0);
968c2ecf20Sopenharmony_ci		} else {
978c2ecf20Sopenharmony_ci			if (!PATH_H_POSITION(tb->tb_path, 1))
988c2ecf20Sopenharmony_ci				replace_key(tb, tb->CFL[0], tb->lkey[0],
998c2ecf20Sopenharmony_ci					    PATH_H_PPARENT(tb->tb_path, 0), 0);
1008c2ecf20Sopenharmony_ci		}
1018c2ecf20Sopenharmony_ci	}
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci	RFALSE(!item_pos && !tb->CFL[0],
1048c2ecf20Sopenharmony_ci	       "PAP-12020: tb->CFL[0]==%p, tb->L[0]==%p", tb->CFL[0],
1058c2ecf20Sopenharmony_ci	       tb->L[0]);
1068c2ecf20Sopenharmony_ci}
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_ci/* cut item in S[0] */
1098c2ecf20Sopenharmony_cistatic void balance_leaf_when_delete_cut(struct tree_balance *tb)
1108c2ecf20Sopenharmony_ci{
1118c2ecf20Sopenharmony_ci	struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path);
1128c2ecf20Sopenharmony_ci	int item_pos = PATH_LAST_POSITION(tb->tb_path);
1138c2ecf20Sopenharmony_ci	struct item_head *ih = item_head(tbS0, item_pos);
1148c2ecf20Sopenharmony_ci	int pos_in_item = tb->tb_path->pos_in_item;
1158c2ecf20Sopenharmony_ci	struct buffer_info bi;
1168c2ecf20Sopenharmony_ci	buffer_info_init_tbS0(tb, &bi);
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_ci	if (is_direntry_le_ih(ih)) {
1198c2ecf20Sopenharmony_ci		/*
1208c2ecf20Sopenharmony_ci		 * UFS unlink semantics are such that you can only
1218c2ecf20Sopenharmony_ci		 * delete one directory entry at a time.
1228c2ecf20Sopenharmony_ci		 *
1238c2ecf20Sopenharmony_ci		 * when we cut a directory tb->insert_size[0] means
1248c2ecf20Sopenharmony_ci		 * number of entries to be cut (always 1)
1258c2ecf20Sopenharmony_ci		 */
1268c2ecf20Sopenharmony_ci		tb->insert_size[0] = -1;
1278c2ecf20Sopenharmony_ci		leaf_cut_from_buffer(&bi, item_pos, pos_in_item,
1288c2ecf20Sopenharmony_ci				     -tb->insert_size[0]);
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_ci		RFALSE(!item_pos && !pos_in_item && !tb->CFL[0],
1318c2ecf20Sopenharmony_ci		       "PAP-12030: can not change delimiting key. CFL[0]=%p",
1328c2ecf20Sopenharmony_ci		       tb->CFL[0]);
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_ci		if (!item_pos && !pos_in_item && tb->CFL[0])
1358c2ecf20Sopenharmony_ci			replace_key(tb, tb->CFL[0], tb->lkey[0], tbS0, 0);
1368c2ecf20Sopenharmony_ci	} else {
1378c2ecf20Sopenharmony_ci		leaf_cut_from_buffer(&bi, item_pos, pos_in_item,
1388c2ecf20Sopenharmony_ci				     -tb->insert_size[0]);
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_ci		RFALSE(!ih_item_len(ih),
1418c2ecf20Sopenharmony_ci		       "PAP-12035: cut must leave non-zero dynamic "
1428c2ecf20Sopenharmony_ci		       "length of item");
1438c2ecf20Sopenharmony_ci	}
1448c2ecf20Sopenharmony_ci}
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_cistatic int balance_leaf_when_delete_left(struct tree_balance *tb)
1478c2ecf20Sopenharmony_ci{
1488c2ecf20Sopenharmony_ci	struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path);
1498c2ecf20Sopenharmony_ci	int n = B_NR_ITEMS(tbS0);
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_ci	/* L[0] must be joined with S[0] */
1528c2ecf20Sopenharmony_ci	if (tb->lnum[0] == -1) {
1538c2ecf20Sopenharmony_ci		/* R[0] must be also joined with S[0] */
1548c2ecf20Sopenharmony_ci		if (tb->rnum[0] == -1) {
1558c2ecf20Sopenharmony_ci			if (tb->FR[0] == PATH_H_PPARENT(tb->tb_path, 0)) {
1568c2ecf20Sopenharmony_ci				/*
1578c2ecf20Sopenharmony_ci				 * all contents of all the
1588c2ecf20Sopenharmony_ci				 * 3 buffers will be in L[0]
1598c2ecf20Sopenharmony_ci				 */
1608c2ecf20Sopenharmony_ci				if (PATH_H_POSITION(tb->tb_path, 1) == 0 &&
1618c2ecf20Sopenharmony_ci				    1 < B_NR_ITEMS(tb->FR[0]))
1628c2ecf20Sopenharmony_ci					replace_key(tb, tb->CFL[0],
1638c2ecf20Sopenharmony_ci						    tb->lkey[0], tb->FR[0], 1);
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci				leaf_move_items(LEAF_FROM_S_TO_L, tb, n, -1,
1668c2ecf20Sopenharmony_ci						NULL);
1678c2ecf20Sopenharmony_ci				leaf_move_items(LEAF_FROM_R_TO_L, tb,
1688c2ecf20Sopenharmony_ci						B_NR_ITEMS(tb->R[0]), -1,
1698c2ecf20Sopenharmony_ci						NULL);
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_ci				reiserfs_invalidate_buffer(tb, tbS0);
1728c2ecf20Sopenharmony_ci				reiserfs_invalidate_buffer(tb, tb->R[0]);
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ci				return 0;
1758c2ecf20Sopenharmony_ci			}
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_ci			/* all contents of all the 3 buffers will be in R[0] */
1788c2ecf20Sopenharmony_ci			leaf_move_items(LEAF_FROM_S_TO_R, tb, n, -1, NULL);
1798c2ecf20Sopenharmony_ci			leaf_move_items(LEAF_FROM_L_TO_R, tb,
1808c2ecf20Sopenharmony_ci					B_NR_ITEMS(tb->L[0]), -1, NULL);
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_ci			/* right_delimiting_key is correct in R[0] */
1838c2ecf20Sopenharmony_ci			replace_key(tb, tb->CFR[0], tb->rkey[0], tb->R[0], 0);
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_ci			reiserfs_invalidate_buffer(tb, tbS0);
1868c2ecf20Sopenharmony_ci			reiserfs_invalidate_buffer(tb, tb->L[0]);
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ci			return -1;
1898c2ecf20Sopenharmony_ci		}
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci		RFALSE(tb->rnum[0] != 0,
1928c2ecf20Sopenharmony_ci		       "PAP-12045: rnum must be 0 (%d)", tb->rnum[0]);
1938c2ecf20Sopenharmony_ci		/* all contents of L[0] and S[0] will be in L[0] */
1948c2ecf20Sopenharmony_ci		leaf_shift_left(tb, n, -1);
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_ci		reiserfs_invalidate_buffer(tb, tbS0);
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_ci		return 0;
1998c2ecf20Sopenharmony_ci	}
2008c2ecf20Sopenharmony_ci
2018c2ecf20Sopenharmony_ci	/*
2028c2ecf20Sopenharmony_ci	 * a part of contents of S[0] will be in L[0] and
2038c2ecf20Sopenharmony_ci	 * the rest part of S[0] will be in R[0]
2048c2ecf20Sopenharmony_ci	 */
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_ci	RFALSE((tb->lnum[0] + tb->rnum[0] < n) ||
2078c2ecf20Sopenharmony_ci	       (tb->lnum[0] + tb->rnum[0] > n + 1),
2088c2ecf20Sopenharmony_ci	       "PAP-12050: rnum(%d) and lnum(%d) and item "
2098c2ecf20Sopenharmony_ci	       "number(%d) in S[0] are not consistent",
2108c2ecf20Sopenharmony_ci	       tb->rnum[0], tb->lnum[0], n);
2118c2ecf20Sopenharmony_ci	RFALSE((tb->lnum[0] + tb->rnum[0] == n) &&
2128c2ecf20Sopenharmony_ci	       (tb->lbytes != -1 || tb->rbytes != -1),
2138c2ecf20Sopenharmony_ci	       "PAP-12055: bad rbytes (%d)/lbytes (%d) "
2148c2ecf20Sopenharmony_ci	       "parameters when items are not split",
2158c2ecf20Sopenharmony_ci	       tb->rbytes, tb->lbytes);
2168c2ecf20Sopenharmony_ci	RFALSE((tb->lnum[0] + tb->rnum[0] == n + 1) &&
2178c2ecf20Sopenharmony_ci	       (tb->lbytes < 1 || tb->rbytes != -1),
2188c2ecf20Sopenharmony_ci	       "PAP-12060: bad rbytes (%d)/lbytes (%d) "
2198c2ecf20Sopenharmony_ci	       "parameters when items are split",
2208c2ecf20Sopenharmony_ci	       tb->rbytes, tb->lbytes);
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci	leaf_shift_left(tb, tb->lnum[0], tb->lbytes);
2238c2ecf20Sopenharmony_ci	leaf_shift_right(tb, tb->rnum[0], tb->rbytes);
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_ci	reiserfs_invalidate_buffer(tb, tbS0);
2268c2ecf20Sopenharmony_ci
2278c2ecf20Sopenharmony_ci	return 0;
2288c2ecf20Sopenharmony_ci}
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_ci/*
2318c2ecf20Sopenharmony_ci * Balance leaf node in case of delete or cut: insert_size[0] < 0
2328c2ecf20Sopenharmony_ci *
2338c2ecf20Sopenharmony_ci * lnum, rnum can have values >= -1
2348c2ecf20Sopenharmony_ci *	-1 means that the neighbor must be joined with S
2358c2ecf20Sopenharmony_ci *	 0 means that nothing should be done with the neighbor
2368c2ecf20Sopenharmony_ci *	>0 means to shift entirely or partly the specified number of items
2378c2ecf20Sopenharmony_ci *         to the neighbor
2388c2ecf20Sopenharmony_ci */
2398c2ecf20Sopenharmony_cistatic int balance_leaf_when_delete(struct tree_balance *tb, int flag)
2408c2ecf20Sopenharmony_ci{
2418c2ecf20Sopenharmony_ci	struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path);
2428c2ecf20Sopenharmony_ci	struct buffer_info bi;
2438c2ecf20Sopenharmony_ci	int n;
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_ci	RFALSE(tb->FR[0] && B_LEVEL(tb->FR[0]) != DISK_LEAF_NODE_LEVEL + 1,
2468c2ecf20Sopenharmony_ci	       "vs- 12000: level: wrong FR %z", tb->FR[0]);
2478c2ecf20Sopenharmony_ci	RFALSE(tb->blknum[0] > 1,
2488c2ecf20Sopenharmony_ci	       "PAP-12005: tb->blknum == %d, can not be > 1", tb->blknum[0]);
2498c2ecf20Sopenharmony_ci	RFALSE(!tb->blknum[0] && !PATH_H_PPARENT(tb->tb_path, 0),
2508c2ecf20Sopenharmony_ci	       "PAP-12010: tree can not be empty");
2518c2ecf20Sopenharmony_ci
2528c2ecf20Sopenharmony_ci	buffer_info_init_tbS0(tb, &bi);
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_ci	/* Delete or truncate the item */
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_ci	BUG_ON(flag != M_DELETE && flag != M_CUT);
2578c2ecf20Sopenharmony_ci	if (flag == M_DELETE)
2588c2ecf20Sopenharmony_ci		balance_leaf_when_delete_del(tb);
2598c2ecf20Sopenharmony_ci	else /* M_CUT */
2608c2ecf20Sopenharmony_ci		balance_leaf_when_delete_cut(tb);
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_ci	/*
2648c2ecf20Sopenharmony_ci	 * the rule is that no shifting occurs unless by shifting
2658c2ecf20Sopenharmony_ci	 * a node can be freed
2668c2ecf20Sopenharmony_ci	 */
2678c2ecf20Sopenharmony_ci	n = B_NR_ITEMS(tbS0);
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_ci
2708c2ecf20Sopenharmony_ci	/* L[0] takes part in balancing */
2718c2ecf20Sopenharmony_ci	if (tb->lnum[0])
2728c2ecf20Sopenharmony_ci		return balance_leaf_when_delete_left(tb);
2738c2ecf20Sopenharmony_ci
2748c2ecf20Sopenharmony_ci	if (tb->rnum[0] == -1) {
2758c2ecf20Sopenharmony_ci		/* all contents of R[0] and S[0] will be in R[0] */
2768c2ecf20Sopenharmony_ci		leaf_shift_right(tb, n, -1);
2778c2ecf20Sopenharmony_ci		reiserfs_invalidate_buffer(tb, tbS0);
2788c2ecf20Sopenharmony_ci		return 0;
2798c2ecf20Sopenharmony_ci	}
2808c2ecf20Sopenharmony_ci
2818c2ecf20Sopenharmony_ci	RFALSE(tb->rnum[0],
2828c2ecf20Sopenharmony_ci	       "PAP-12065: bad rnum parameter must be 0 (%d)", tb->rnum[0]);
2838c2ecf20Sopenharmony_ci	return 0;
2848c2ecf20Sopenharmony_ci}
2858c2ecf20Sopenharmony_ci
2868c2ecf20Sopenharmony_cistatic unsigned int balance_leaf_insert_left(struct tree_balance *tb,
2878c2ecf20Sopenharmony_ci					     struct item_head *const ih,
2888c2ecf20Sopenharmony_ci					     const char * const body)
2898c2ecf20Sopenharmony_ci{
2908c2ecf20Sopenharmony_ci	int ret;
2918c2ecf20Sopenharmony_ci	struct buffer_info bi;
2928c2ecf20Sopenharmony_ci	int n = B_NR_ITEMS(tb->L[0]);
2938c2ecf20Sopenharmony_ci	unsigned body_shift_bytes = 0;
2948c2ecf20Sopenharmony_ci
2958c2ecf20Sopenharmony_ci	if (tb->item_pos == tb->lnum[0] - 1 && tb->lbytes != -1) {
2968c2ecf20Sopenharmony_ci		/* part of new item falls into L[0] */
2978c2ecf20Sopenharmony_ci		int new_item_len, shift;
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_ci		ret = leaf_shift_left(tb, tb->lnum[0] - 1, -1);
3008c2ecf20Sopenharmony_ci
3018c2ecf20Sopenharmony_ci		/* Calculate item length to insert to S[0] */
3028c2ecf20Sopenharmony_ci		new_item_len = ih_item_len(ih) - tb->lbytes;
3038c2ecf20Sopenharmony_ci
3048c2ecf20Sopenharmony_ci		/* Calculate and check item length to insert to L[0] */
3058c2ecf20Sopenharmony_ci		put_ih_item_len(ih, ih_item_len(ih) - new_item_len);
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_ci		RFALSE(ih_item_len(ih) <= 0,
3088c2ecf20Sopenharmony_ci		       "PAP-12080: there is nothing to insert into L[0]: "
3098c2ecf20Sopenharmony_ci		       "ih_item_len=%d", ih_item_len(ih));
3108c2ecf20Sopenharmony_ci
3118c2ecf20Sopenharmony_ci		/* Insert new item into L[0] */
3128c2ecf20Sopenharmony_ci		buffer_info_init_left(tb, &bi);
3138c2ecf20Sopenharmony_ci		leaf_insert_into_buf(&bi, n + tb->item_pos - ret, ih, body,
3148c2ecf20Sopenharmony_ci			     min_t(int, tb->zeroes_num, ih_item_len(ih)));
3158c2ecf20Sopenharmony_ci
3168c2ecf20Sopenharmony_ci		/*
3178c2ecf20Sopenharmony_ci		 * Calculate key component, item length and body to
3188c2ecf20Sopenharmony_ci		 * insert into S[0]
3198c2ecf20Sopenharmony_ci		 */
3208c2ecf20Sopenharmony_ci		shift = 0;
3218c2ecf20Sopenharmony_ci		if (is_indirect_le_ih(ih))
3228c2ecf20Sopenharmony_ci			shift = tb->tb_sb->s_blocksize_bits - UNFM_P_SHIFT;
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_ci		add_le_ih_k_offset(ih, tb->lbytes << shift);
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_ci		put_ih_item_len(ih, new_item_len);
3278c2ecf20Sopenharmony_ci		if (tb->lbytes > tb->zeroes_num) {
3288c2ecf20Sopenharmony_ci			body_shift_bytes = tb->lbytes - tb->zeroes_num;
3298c2ecf20Sopenharmony_ci			tb->zeroes_num = 0;
3308c2ecf20Sopenharmony_ci		} else
3318c2ecf20Sopenharmony_ci			tb->zeroes_num -= tb->lbytes;
3328c2ecf20Sopenharmony_ci
3338c2ecf20Sopenharmony_ci		RFALSE(ih_item_len(ih) <= 0,
3348c2ecf20Sopenharmony_ci		       "PAP-12085: there is nothing to insert into S[0]: "
3358c2ecf20Sopenharmony_ci		       "ih_item_len=%d", ih_item_len(ih));
3368c2ecf20Sopenharmony_ci	} else {
3378c2ecf20Sopenharmony_ci		/* new item in whole falls into L[0] */
3388c2ecf20Sopenharmony_ci		/* Shift lnum[0]-1 items to L[0] */
3398c2ecf20Sopenharmony_ci		ret = leaf_shift_left(tb, tb->lnum[0] - 1, tb->lbytes);
3408c2ecf20Sopenharmony_ci
3418c2ecf20Sopenharmony_ci		/* Insert new item into L[0] */
3428c2ecf20Sopenharmony_ci		buffer_info_init_left(tb, &bi);
3438c2ecf20Sopenharmony_ci		leaf_insert_into_buf(&bi, n + tb->item_pos - ret, ih, body,
3448c2ecf20Sopenharmony_ci				     tb->zeroes_num);
3458c2ecf20Sopenharmony_ci		tb->insert_size[0] = 0;
3468c2ecf20Sopenharmony_ci		tb->zeroes_num = 0;
3478c2ecf20Sopenharmony_ci	}
3488c2ecf20Sopenharmony_ci	return body_shift_bytes;
3498c2ecf20Sopenharmony_ci}
3508c2ecf20Sopenharmony_ci
3518c2ecf20Sopenharmony_cistatic void balance_leaf_paste_left_shift_dirent(struct tree_balance *tb,
3528c2ecf20Sopenharmony_ci						 struct item_head * const ih,
3538c2ecf20Sopenharmony_ci						 const char * const body)
3548c2ecf20Sopenharmony_ci{
3558c2ecf20Sopenharmony_ci	int n = B_NR_ITEMS(tb->L[0]);
3568c2ecf20Sopenharmony_ci	struct buffer_info bi;
3578c2ecf20Sopenharmony_ci
3588c2ecf20Sopenharmony_ci	RFALSE(tb->zeroes_num,
3598c2ecf20Sopenharmony_ci	       "PAP-12090: invalid parameter in case of a directory");
3608c2ecf20Sopenharmony_ci
3618c2ecf20Sopenharmony_ci	/* directory item */
3628c2ecf20Sopenharmony_ci	if (tb->lbytes > tb->pos_in_item) {
3638c2ecf20Sopenharmony_ci		/* new directory entry falls into L[0] */
3648c2ecf20Sopenharmony_ci		struct item_head *pasted;
3658c2ecf20Sopenharmony_ci		int ret, l_pos_in_item = tb->pos_in_item;
3668c2ecf20Sopenharmony_ci
3678c2ecf20Sopenharmony_ci		/*
3688c2ecf20Sopenharmony_ci		 * Shift lnum[0] - 1 items in whole.
3698c2ecf20Sopenharmony_ci		 * Shift lbytes - 1 entries from given directory item
3708c2ecf20Sopenharmony_ci		 */
3718c2ecf20Sopenharmony_ci		ret = leaf_shift_left(tb, tb->lnum[0], tb->lbytes - 1);
3728c2ecf20Sopenharmony_ci		if (ret && !tb->item_pos) {
3738c2ecf20Sopenharmony_ci			pasted = item_head(tb->L[0], B_NR_ITEMS(tb->L[0]) - 1);
3748c2ecf20Sopenharmony_ci			l_pos_in_item += ih_entry_count(pasted) -
3758c2ecf20Sopenharmony_ci					 (tb->lbytes - 1);
3768c2ecf20Sopenharmony_ci		}
3778c2ecf20Sopenharmony_ci
3788c2ecf20Sopenharmony_ci		/* Append given directory entry to directory item */
3798c2ecf20Sopenharmony_ci		buffer_info_init_left(tb, &bi);
3808c2ecf20Sopenharmony_ci		leaf_paste_in_buffer(&bi, n + tb->item_pos - ret,
3818c2ecf20Sopenharmony_ci				     l_pos_in_item, tb->insert_size[0],
3828c2ecf20Sopenharmony_ci				     body, tb->zeroes_num);
3838c2ecf20Sopenharmony_ci
3848c2ecf20Sopenharmony_ci		/*
3858c2ecf20Sopenharmony_ci		 * previous string prepared space for pasting new entry,
3868c2ecf20Sopenharmony_ci		 * following string pastes this entry
3878c2ecf20Sopenharmony_ci		 */
3888c2ecf20Sopenharmony_ci
3898c2ecf20Sopenharmony_ci		/*
3908c2ecf20Sopenharmony_ci		 * when we have merge directory item, pos_in_item
3918c2ecf20Sopenharmony_ci		 * has been changed too
3928c2ecf20Sopenharmony_ci		 */
3938c2ecf20Sopenharmony_ci
3948c2ecf20Sopenharmony_ci		/* paste new directory entry. 1 is entry number */
3958c2ecf20Sopenharmony_ci		leaf_paste_entries(&bi, n + tb->item_pos - ret,
3968c2ecf20Sopenharmony_ci				   l_pos_in_item, 1,
3978c2ecf20Sopenharmony_ci				   (struct reiserfs_de_head *) body,
3988c2ecf20Sopenharmony_ci				   body + DEH_SIZE, tb->insert_size[0]);
3998c2ecf20Sopenharmony_ci		tb->insert_size[0] = 0;
4008c2ecf20Sopenharmony_ci	} else {
4018c2ecf20Sopenharmony_ci		/* new directory item doesn't fall into L[0] */
4028c2ecf20Sopenharmony_ci		/*
4038c2ecf20Sopenharmony_ci		 * Shift lnum[0]-1 items in whole. Shift lbytes
4048c2ecf20Sopenharmony_ci		 * directory entries from directory item number lnum[0]
4058c2ecf20Sopenharmony_ci		 */
4068c2ecf20Sopenharmony_ci		leaf_shift_left(tb, tb->lnum[0], tb->lbytes);
4078c2ecf20Sopenharmony_ci	}
4088c2ecf20Sopenharmony_ci
4098c2ecf20Sopenharmony_ci	/* Calculate new position to append in item body */
4108c2ecf20Sopenharmony_ci	tb->pos_in_item -= tb->lbytes;
4118c2ecf20Sopenharmony_ci}
4128c2ecf20Sopenharmony_ci
4138c2ecf20Sopenharmony_cistatic unsigned int balance_leaf_paste_left_shift(struct tree_balance *tb,
4148c2ecf20Sopenharmony_ci						  struct item_head * const ih,
4158c2ecf20Sopenharmony_ci						  const char * const body)
4168c2ecf20Sopenharmony_ci{
4178c2ecf20Sopenharmony_ci	struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path);
4188c2ecf20Sopenharmony_ci	int n = B_NR_ITEMS(tb->L[0]);
4198c2ecf20Sopenharmony_ci	struct buffer_info bi;
4208c2ecf20Sopenharmony_ci	int body_shift_bytes = 0;
4218c2ecf20Sopenharmony_ci
4228c2ecf20Sopenharmony_ci	if (is_direntry_le_ih(item_head(tbS0, tb->item_pos))) {
4238c2ecf20Sopenharmony_ci		balance_leaf_paste_left_shift_dirent(tb, ih, body);
4248c2ecf20Sopenharmony_ci		return 0;
4258c2ecf20Sopenharmony_ci	}
4268c2ecf20Sopenharmony_ci
4278c2ecf20Sopenharmony_ci	RFALSE(tb->lbytes <= 0,
4288c2ecf20Sopenharmony_ci	       "PAP-12095: there is nothing to shift to L[0]. "
4298c2ecf20Sopenharmony_ci	       "lbytes=%d", tb->lbytes);
4308c2ecf20Sopenharmony_ci	RFALSE(tb->pos_in_item != ih_item_len(item_head(tbS0, tb->item_pos)),
4318c2ecf20Sopenharmony_ci	       "PAP-12100: incorrect position to paste: "
4328c2ecf20Sopenharmony_ci	       "item_len=%d, pos_in_item=%d",
4338c2ecf20Sopenharmony_ci	       ih_item_len(item_head(tbS0, tb->item_pos)), tb->pos_in_item);
4348c2ecf20Sopenharmony_ci
4358c2ecf20Sopenharmony_ci	/* appended item will be in L[0] in whole */
4368c2ecf20Sopenharmony_ci	if (tb->lbytes >= tb->pos_in_item) {
4378c2ecf20Sopenharmony_ci		struct item_head *tbS0_pos_ih, *tbL0_ih;
4388c2ecf20Sopenharmony_ci		struct item_head *tbS0_0_ih;
4398c2ecf20Sopenharmony_ci		struct reiserfs_key *left_delim_key;
4408c2ecf20Sopenharmony_ci		int ret, l_n, version, temp_l;
4418c2ecf20Sopenharmony_ci
4428c2ecf20Sopenharmony_ci		tbS0_pos_ih = item_head(tbS0, tb->item_pos);
4438c2ecf20Sopenharmony_ci		tbS0_0_ih = item_head(tbS0, 0);
4448c2ecf20Sopenharmony_ci
4458c2ecf20Sopenharmony_ci		/*
4468c2ecf20Sopenharmony_ci		 * this bytes number must be appended
4478c2ecf20Sopenharmony_ci		 * to the last item of L[h]
4488c2ecf20Sopenharmony_ci		 */
4498c2ecf20Sopenharmony_ci		l_n = tb->lbytes - tb->pos_in_item;
4508c2ecf20Sopenharmony_ci
4518c2ecf20Sopenharmony_ci		/* Calculate new insert_size[0] */
4528c2ecf20Sopenharmony_ci		tb->insert_size[0] -= l_n;
4538c2ecf20Sopenharmony_ci
4548c2ecf20Sopenharmony_ci		RFALSE(tb->insert_size[0] <= 0,
4558c2ecf20Sopenharmony_ci		       "PAP-12105: there is nothing to paste into "
4568c2ecf20Sopenharmony_ci		       "L[0]. insert_size=%d", tb->insert_size[0]);
4578c2ecf20Sopenharmony_ci
4588c2ecf20Sopenharmony_ci		ret = leaf_shift_left(tb, tb->lnum[0],
4598c2ecf20Sopenharmony_ci				      ih_item_len(tbS0_pos_ih));
4608c2ecf20Sopenharmony_ci
4618c2ecf20Sopenharmony_ci		tbL0_ih = item_head(tb->L[0], n + tb->item_pos - ret);
4628c2ecf20Sopenharmony_ci
4638c2ecf20Sopenharmony_ci		/* Append to body of item in L[0] */
4648c2ecf20Sopenharmony_ci		buffer_info_init_left(tb, &bi);
4658c2ecf20Sopenharmony_ci		leaf_paste_in_buffer(&bi, n + tb->item_pos - ret,
4668c2ecf20Sopenharmony_ci				     ih_item_len(tbL0_ih), l_n, body,
4678c2ecf20Sopenharmony_ci				     min_t(int, l_n, tb->zeroes_num));
4688c2ecf20Sopenharmony_ci
4698c2ecf20Sopenharmony_ci		/*
4708c2ecf20Sopenharmony_ci		 * 0-th item in S0 can be only of DIRECT type
4718c2ecf20Sopenharmony_ci		 * when l_n != 0
4728c2ecf20Sopenharmony_ci		 */
4738c2ecf20Sopenharmony_ci		temp_l = l_n;
4748c2ecf20Sopenharmony_ci
4758c2ecf20Sopenharmony_ci		RFALSE(ih_item_len(tbS0_0_ih),
4768c2ecf20Sopenharmony_ci		       "PAP-12106: item length must be 0");
4778c2ecf20Sopenharmony_ci		RFALSE(comp_short_le_keys(&tbS0_0_ih->ih_key,
4788c2ecf20Sopenharmony_ci		       leaf_key(tb->L[0], n + tb->item_pos - ret)),
4798c2ecf20Sopenharmony_ci		       "PAP-12107: items must be of the same file");
4808c2ecf20Sopenharmony_ci
4818c2ecf20Sopenharmony_ci		if (is_indirect_le_ih(tbL0_ih)) {
4828c2ecf20Sopenharmony_ci			int shift = tb->tb_sb->s_blocksize_bits - UNFM_P_SHIFT;
4838c2ecf20Sopenharmony_ci			temp_l = l_n << shift;
4848c2ecf20Sopenharmony_ci		}
4858c2ecf20Sopenharmony_ci		/* update key of first item in S0 */
4868c2ecf20Sopenharmony_ci		version = ih_version(tbS0_0_ih);
4878c2ecf20Sopenharmony_ci		add_le_key_k_offset(version, &tbS0_0_ih->ih_key, temp_l);
4888c2ecf20Sopenharmony_ci
4898c2ecf20Sopenharmony_ci		/* update left delimiting key */
4908c2ecf20Sopenharmony_ci		left_delim_key = internal_key(tb->CFL[0], tb->lkey[0]);
4918c2ecf20Sopenharmony_ci		add_le_key_k_offset(version, left_delim_key, temp_l);
4928c2ecf20Sopenharmony_ci
4938c2ecf20Sopenharmony_ci		/*
4948c2ecf20Sopenharmony_ci		 * Calculate new body, position in item and
4958c2ecf20Sopenharmony_ci		 * insert_size[0]
4968c2ecf20Sopenharmony_ci		 */
4978c2ecf20Sopenharmony_ci		if (l_n > tb->zeroes_num) {
4988c2ecf20Sopenharmony_ci			body_shift_bytes = l_n - tb->zeroes_num;
4998c2ecf20Sopenharmony_ci			tb->zeroes_num = 0;
5008c2ecf20Sopenharmony_ci		} else
5018c2ecf20Sopenharmony_ci			tb->zeroes_num -= l_n;
5028c2ecf20Sopenharmony_ci		tb->pos_in_item = 0;
5038c2ecf20Sopenharmony_ci
5048c2ecf20Sopenharmony_ci		RFALSE(comp_short_le_keys(&tbS0_0_ih->ih_key,
5058c2ecf20Sopenharmony_ci					  leaf_key(tb->L[0],
5068c2ecf20Sopenharmony_ci						 B_NR_ITEMS(tb->L[0]) - 1)) ||
5078c2ecf20Sopenharmony_ci		       !op_is_left_mergeable(leaf_key(tbS0, 0), tbS0->b_size) ||
5088c2ecf20Sopenharmony_ci		       !op_is_left_mergeable(left_delim_key, tbS0->b_size),
5098c2ecf20Sopenharmony_ci		       "PAP-12120: item must be merge-able with left "
5108c2ecf20Sopenharmony_ci		       "neighboring item");
5118c2ecf20Sopenharmony_ci	} else {
5128c2ecf20Sopenharmony_ci		/* only part of the appended item will be in L[0] */
5138c2ecf20Sopenharmony_ci
5148c2ecf20Sopenharmony_ci		/* Calculate position in item for append in S[0] */
5158c2ecf20Sopenharmony_ci		tb->pos_in_item -= tb->lbytes;
5168c2ecf20Sopenharmony_ci
5178c2ecf20Sopenharmony_ci		RFALSE(tb->pos_in_item <= 0,
5188c2ecf20Sopenharmony_ci		       "PAP-12125: no place for paste. pos_in_item=%d",
5198c2ecf20Sopenharmony_ci		       tb->pos_in_item);
5208c2ecf20Sopenharmony_ci
5218c2ecf20Sopenharmony_ci		/*
5228c2ecf20Sopenharmony_ci		 * Shift lnum[0] - 1 items in whole.
5238c2ecf20Sopenharmony_ci		 * Shift lbytes - 1 byte from item number lnum[0]
5248c2ecf20Sopenharmony_ci		 */
5258c2ecf20Sopenharmony_ci		leaf_shift_left(tb, tb->lnum[0], tb->lbytes);
5268c2ecf20Sopenharmony_ci	}
5278c2ecf20Sopenharmony_ci	return body_shift_bytes;
5288c2ecf20Sopenharmony_ci}
5298c2ecf20Sopenharmony_ci
5308c2ecf20Sopenharmony_ci
5318c2ecf20Sopenharmony_ci/* appended item will be in L[0] in whole */
5328c2ecf20Sopenharmony_cistatic void balance_leaf_paste_left_whole(struct tree_balance *tb,
5338c2ecf20Sopenharmony_ci					  struct item_head * const ih,
5348c2ecf20Sopenharmony_ci					  const char * const body)
5358c2ecf20Sopenharmony_ci{
5368c2ecf20Sopenharmony_ci	struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path);
5378c2ecf20Sopenharmony_ci	int n = B_NR_ITEMS(tb->L[0]);
5388c2ecf20Sopenharmony_ci	struct buffer_info bi;
5398c2ecf20Sopenharmony_ci	struct item_head *pasted;
5408c2ecf20Sopenharmony_ci	int ret;
5418c2ecf20Sopenharmony_ci
5428c2ecf20Sopenharmony_ci	/* if we paste into first item of S[0] and it is left mergable */
5438c2ecf20Sopenharmony_ci	if (!tb->item_pos &&
5448c2ecf20Sopenharmony_ci	    op_is_left_mergeable(leaf_key(tbS0, 0), tbS0->b_size)) {
5458c2ecf20Sopenharmony_ci		/*
5468c2ecf20Sopenharmony_ci		 * then increment pos_in_item by the size of the
5478c2ecf20Sopenharmony_ci		 * last item in L[0]
5488c2ecf20Sopenharmony_ci		 */
5498c2ecf20Sopenharmony_ci		pasted = item_head(tb->L[0], n - 1);
5508c2ecf20Sopenharmony_ci		if (is_direntry_le_ih(pasted))
5518c2ecf20Sopenharmony_ci			tb->pos_in_item += ih_entry_count(pasted);
5528c2ecf20Sopenharmony_ci		else
5538c2ecf20Sopenharmony_ci			tb->pos_in_item += ih_item_len(pasted);
5548c2ecf20Sopenharmony_ci	}
5558c2ecf20Sopenharmony_ci
5568c2ecf20Sopenharmony_ci	/*
5578c2ecf20Sopenharmony_ci	 * Shift lnum[0] - 1 items in whole.
5588c2ecf20Sopenharmony_ci	 * Shift lbytes - 1 byte from item number lnum[0]
5598c2ecf20Sopenharmony_ci	 */
5608c2ecf20Sopenharmony_ci	ret = leaf_shift_left(tb, tb->lnum[0], tb->lbytes);
5618c2ecf20Sopenharmony_ci
5628c2ecf20Sopenharmony_ci	/* Append to body of item in L[0] */
5638c2ecf20Sopenharmony_ci	buffer_info_init_left(tb, &bi);
5648c2ecf20Sopenharmony_ci	leaf_paste_in_buffer(&bi, n + tb->item_pos - ret, tb->pos_in_item,
5658c2ecf20Sopenharmony_ci			     tb->insert_size[0], body, tb->zeroes_num);
5668c2ecf20Sopenharmony_ci
5678c2ecf20Sopenharmony_ci	/* if appended item is directory, paste entry */
5688c2ecf20Sopenharmony_ci	pasted = item_head(tb->L[0], n + tb->item_pos - ret);
5698c2ecf20Sopenharmony_ci	if (is_direntry_le_ih(pasted))
5708c2ecf20Sopenharmony_ci		leaf_paste_entries(&bi, n + tb->item_pos - ret,
5718c2ecf20Sopenharmony_ci				   tb->pos_in_item, 1,
5728c2ecf20Sopenharmony_ci				   (struct reiserfs_de_head *)body,
5738c2ecf20Sopenharmony_ci				   body + DEH_SIZE, tb->insert_size[0]);
5748c2ecf20Sopenharmony_ci
5758c2ecf20Sopenharmony_ci	/*
5768c2ecf20Sopenharmony_ci	 * if appended item is indirect item, put unformatted node
5778c2ecf20Sopenharmony_ci	 * into un list
5788c2ecf20Sopenharmony_ci	 */
5798c2ecf20Sopenharmony_ci	if (is_indirect_le_ih(pasted))
5808c2ecf20Sopenharmony_ci		set_ih_free_space(pasted, 0);
5818c2ecf20Sopenharmony_ci
5828c2ecf20Sopenharmony_ci	tb->insert_size[0] = 0;
5838c2ecf20Sopenharmony_ci	tb->zeroes_num = 0;
5848c2ecf20Sopenharmony_ci}
5858c2ecf20Sopenharmony_ci
5868c2ecf20Sopenharmony_cistatic unsigned int balance_leaf_paste_left(struct tree_balance *tb,
5878c2ecf20Sopenharmony_ci					    struct item_head * const ih,
5888c2ecf20Sopenharmony_ci					    const char * const body)
5898c2ecf20Sopenharmony_ci{
5908c2ecf20Sopenharmony_ci	/* we must shift the part of the appended item */
5918c2ecf20Sopenharmony_ci	if (tb->item_pos == tb->lnum[0] - 1 && tb->lbytes != -1)
5928c2ecf20Sopenharmony_ci		return balance_leaf_paste_left_shift(tb, ih, body);
5938c2ecf20Sopenharmony_ci	else
5948c2ecf20Sopenharmony_ci		balance_leaf_paste_left_whole(tb, ih, body);
5958c2ecf20Sopenharmony_ci	return 0;
5968c2ecf20Sopenharmony_ci}
5978c2ecf20Sopenharmony_ci
5988c2ecf20Sopenharmony_ci/* Shift lnum[0] items from S[0] to the left neighbor L[0] */
5998c2ecf20Sopenharmony_cistatic unsigned int balance_leaf_left(struct tree_balance *tb,
6008c2ecf20Sopenharmony_ci				      struct item_head * const ih,
6018c2ecf20Sopenharmony_ci				      const char * const body, int flag)
6028c2ecf20Sopenharmony_ci{
6038c2ecf20Sopenharmony_ci	if (tb->lnum[0] <= 0)
6048c2ecf20Sopenharmony_ci		return 0;
6058c2ecf20Sopenharmony_ci
6068c2ecf20Sopenharmony_ci	/* new item or it part falls to L[0], shift it too */
6078c2ecf20Sopenharmony_ci	if (tb->item_pos < tb->lnum[0]) {
6088c2ecf20Sopenharmony_ci		BUG_ON(flag != M_INSERT && flag != M_PASTE);
6098c2ecf20Sopenharmony_ci
6108c2ecf20Sopenharmony_ci		if (flag == M_INSERT)
6118c2ecf20Sopenharmony_ci			return balance_leaf_insert_left(tb, ih, body);
6128c2ecf20Sopenharmony_ci		else /* M_PASTE */
6138c2ecf20Sopenharmony_ci			return balance_leaf_paste_left(tb, ih, body);
6148c2ecf20Sopenharmony_ci	} else
6158c2ecf20Sopenharmony_ci		/* new item doesn't fall into L[0] */
6168c2ecf20Sopenharmony_ci		leaf_shift_left(tb, tb->lnum[0], tb->lbytes);
6178c2ecf20Sopenharmony_ci	return 0;
6188c2ecf20Sopenharmony_ci}
6198c2ecf20Sopenharmony_ci
6208c2ecf20Sopenharmony_ci
6218c2ecf20Sopenharmony_cistatic void balance_leaf_insert_right(struct tree_balance *tb,
6228c2ecf20Sopenharmony_ci				      struct item_head * const ih,
6238c2ecf20Sopenharmony_ci				      const char * const body)
6248c2ecf20Sopenharmony_ci{
6258c2ecf20Sopenharmony_ci
6268c2ecf20Sopenharmony_ci	struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path);
6278c2ecf20Sopenharmony_ci	int n = B_NR_ITEMS(tbS0);
6288c2ecf20Sopenharmony_ci	struct buffer_info bi;
6298c2ecf20Sopenharmony_ci
6308c2ecf20Sopenharmony_ci	/* new item or part of it doesn't fall into R[0] */
6318c2ecf20Sopenharmony_ci	if (n - tb->rnum[0] >= tb->item_pos) {
6328c2ecf20Sopenharmony_ci		leaf_shift_right(tb, tb->rnum[0], tb->rbytes);
6338c2ecf20Sopenharmony_ci		return;
6348c2ecf20Sopenharmony_ci	}
6358c2ecf20Sopenharmony_ci
6368c2ecf20Sopenharmony_ci	/* new item or its part falls to R[0] */
6378c2ecf20Sopenharmony_ci
6388c2ecf20Sopenharmony_ci	/* part of new item falls into R[0] */
6398c2ecf20Sopenharmony_ci	if (tb->item_pos == n - tb->rnum[0] + 1 && tb->rbytes != -1) {
6408c2ecf20Sopenharmony_ci		loff_t old_key_comp, old_len, r_zeroes_number;
6418c2ecf20Sopenharmony_ci		const char *r_body;
6428c2ecf20Sopenharmony_ci		int shift;
6438c2ecf20Sopenharmony_ci		loff_t offset;
6448c2ecf20Sopenharmony_ci
6458c2ecf20Sopenharmony_ci		leaf_shift_right(tb, tb->rnum[0] - 1, -1);
6468c2ecf20Sopenharmony_ci
6478c2ecf20Sopenharmony_ci		/* Remember key component and item length */
6488c2ecf20Sopenharmony_ci		old_key_comp = le_ih_k_offset(ih);
6498c2ecf20Sopenharmony_ci		old_len = ih_item_len(ih);
6508c2ecf20Sopenharmony_ci
6518c2ecf20Sopenharmony_ci		/*
6528c2ecf20Sopenharmony_ci		 * Calculate key component and item length to insert
6538c2ecf20Sopenharmony_ci		 * into R[0]
6548c2ecf20Sopenharmony_ci		 */
6558c2ecf20Sopenharmony_ci		shift = 0;
6568c2ecf20Sopenharmony_ci		if (is_indirect_le_ih(ih))
6578c2ecf20Sopenharmony_ci			shift = tb->tb_sb->s_blocksize_bits - UNFM_P_SHIFT;
6588c2ecf20Sopenharmony_ci		offset = le_ih_k_offset(ih) + ((old_len - tb->rbytes) << shift);
6598c2ecf20Sopenharmony_ci		set_le_ih_k_offset(ih, offset);
6608c2ecf20Sopenharmony_ci		put_ih_item_len(ih, tb->rbytes);
6618c2ecf20Sopenharmony_ci
6628c2ecf20Sopenharmony_ci		/* Insert part of the item into R[0] */
6638c2ecf20Sopenharmony_ci		buffer_info_init_right(tb, &bi);
6648c2ecf20Sopenharmony_ci		if ((old_len - tb->rbytes) > tb->zeroes_num) {
6658c2ecf20Sopenharmony_ci			r_zeroes_number = 0;
6668c2ecf20Sopenharmony_ci			r_body = body + (old_len - tb->rbytes) - tb->zeroes_num;
6678c2ecf20Sopenharmony_ci		} else {
6688c2ecf20Sopenharmony_ci			r_body = body;
6698c2ecf20Sopenharmony_ci			r_zeroes_number = tb->zeroes_num -
6708c2ecf20Sopenharmony_ci					  (old_len - tb->rbytes);
6718c2ecf20Sopenharmony_ci			tb->zeroes_num -= r_zeroes_number;
6728c2ecf20Sopenharmony_ci		}
6738c2ecf20Sopenharmony_ci
6748c2ecf20Sopenharmony_ci		leaf_insert_into_buf(&bi, 0, ih, r_body, r_zeroes_number);
6758c2ecf20Sopenharmony_ci
6768c2ecf20Sopenharmony_ci		/* Replace right delimiting key by first key in R[0] */
6778c2ecf20Sopenharmony_ci		replace_key(tb, tb->CFR[0], tb->rkey[0], tb->R[0], 0);
6788c2ecf20Sopenharmony_ci
6798c2ecf20Sopenharmony_ci		/*
6808c2ecf20Sopenharmony_ci		 * Calculate key component and item length to
6818c2ecf20Sopenharmony_ci		 * insert into S[0]
6828c2ecf20Sopenharmony_ci		 */
6838c2ecf20Sopenharmony_ci		set_le_ih_k_offset(ih, old_key_comp);
6848c2ecf20Sopenharmony_ci		put_ih_item_len(ih, old_len - tb->rbytes);
6858c2ecf20Sopenharmony_ci
6868c2ecf20Sopenharmony_ci		tb->insert_size[0] -= tb->rbytes;
6878c2ecf20Sopenharmony_ci
6888c2ecf20Sopenharmony_ci	} else {
6898c2ecf20Sopenharmony_ci		/* whole new item falls into R[0] */
6908c2ecf20Sopenharmony_ci
6918c2ecf20Sopenharmony_ci		/* Shift rnum[0]-1 items to R[0] */
6928c2ecf20Sopenharmony_ci		leaf_shift_right(tb, tb->rnum[0] - 1, tb->rbytes);
6938c2ecf20Sopenharmony_ci
6948c2ecf20Sopenharmony_ci		/* Insert new item into R[0] */
6958c2ecf20Sopenharmony_ci		buffer_info_init_right(tb, &bi);
6968c2ecf20Sopenharmony_ci		leaf_insert_into_buf(&bi, tb->item_pos - n + tb->rnum[0] - 1,
6978c2ecf20Sopenharmony_ci				     ih, body, tb->zeroes_num);
6988c2ecf20Sopenharmony_ci
6998c2ecf20Sopenharmony_ci		if (tb->item_pos - n + tb->rnum[0] - 1 == 0)
7008c2ecf20Sopenharmony_ci			replace_key(tb, tb->CFR[0], tb->rkey[0], tb->R[0], 0);
7018c2ecf20Sopenharmony_ci
7028c2ecf20Sopenharmony_ci		tb->zeroes_num = tb->insert_size[0] = 0;
7038c2ecf20Sopenharmony_ci	}
7048c2ecf20Sopenharmony_ci}
7058c2ecf20Sopenharmony_ci
7068c2ecf20Sopenharmony_ci
7078c2ecf20Sopenharmony_cistatic void balance_leaf_paste_right_shift_dirent(struct tree_balance *tb,
7088c2ecf20Sopenharmony_ci				     struct item_head * const ih,
7098c2ecf20Sopenharmony_ci				     const char * const body)
7108c2ecf20Sopenharmony_ci{
7118c2ecf20Sopenharmony_ci	struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path);
7128c2ecf20Sopenharmony_ci	struct buffer_info bi;
7138c2ecf20Sopenharmony_ci	int entry_count;
7148c2ecf20Sopenharmony_ci
7158c2ecf20Sopenharmony_ci	RFALSE(tb->zeroes_num,
7168c2ecf20Sopenharmony_ci	       "PAP-12145: invalid parameter in case of a directory");
7178c2ecf20Sopenharmony_ci	entry_count = ih_entry_count(item_head(tbS0, tb->item_pos));
7188c2ecf20Sopenharmony_ci
7198c2ecf20Sopenharmony_ci	/* new directory entry falls into R[0] */
7208c2ecf20Sopenharmony_ci	if (entry_count - tb->rbytes < tb->pos_in_item) {
7218c2ecf20Sopenharmony_ci		int paste_entry_position;
7228c2ecf20Sopenharmony_ci
7238c2ecf20Sopenharmony_ci		RFALSE(tb->rbytes - 1 >= entry_count || !tb->insert_size[0],
7248c2ecf20Sopenharmony_ci		       "PAP-12150: no enough of entries to shift to R[0]: "
7258c2ecf20Sopenharmony_ci		       "rbytes=%d, entry_count=%d", tb->rbytes, entry_count);
7268c2ecf20Sopenharmony_ci
7278c2ecf20Sopenharmony_ci		/*
7288c2ecf20Sopenharmony_ci		 * Shift rnum[0]-1 items in whole.
7298c2ecf20Sopenharmony_ci		 * Shift rbytes-1 directory entries from directory
7308c2ecf20Sopenharmony_ci		 * item number rnum[0]
7318c2ecf20Sopenharmony_ci		 */
7328c2ecf20Sopenharmony_ci		leaf_shift_right(tb, tb->rnum[0], tb->rbytes - 1);
7338c2ecf20Sopenharmony_ci
7348c2ecf20Sopenharmony_ci		/* Paste given directory entry to directory item */
7358c2ecf20Sopenharmony_ci		paste_entry_position = tb->pos_in_item - entry_count +
7368c2ecf20Sopenharmony_ci				       tb->rbytes - 1;
7378c2ecf20Sopenharmony_ci		buffer_info_init_right(tb, &bi);
7388c2ecf20Sopenharmony_ci		leaf_paste_in_buffer(&bi, 0, paste_entry_position,
7398c2ecf20Sopenharmony_ci				     tb->insert_size[0], body, tb->zeroes_num);
7408c2ecf20Sopenharmony_ci
7418c2ecf20Sopenharmony_ci		/* paste entry */
7428c2ecf20Sopenharmony_ci		leaf_paste_entries(&bi, 0, paste_entry_position, 1,
7438c2ecf20Sopenharmony_ci				   (struct reiserfs_de_head *) body,
7448c2ecf20Sopenharmony_ci				   body + DEH_SIZE, tb->insert_size[0]);
7458c2ecf20Sopenharmony_ci
7468c2ecf20Sopenharmony_ci		/* change delimiting keys */
7478c2ecf20Sopenharmony_ci		if (paste_entry_position == 0)
7488c2ecf20Sopenharmony_ci			replace_key(tb, tb->CFR[0], tb->rkey[0], tb->R[0], 0);
7498c2ecf20Sopenharmony_ci
7508c2ecf20Sopenharmony_ci		tb->insert_size[0] = 0;
7518c2ecf20Sopenharmony_ci		tb->pos_in_item++;
7528c2ecf20Sopenharmony_ci	} else {
7538c2ecf20Sopenharmony_ci		/* new directory entry doesn't fall into R[0] */
7548c2ecf20Sopenharmony_ci		leaf_shift_right(tb, tb->rnum[0], tb->rbytes);
7558c2ecf20Sopenharmony_ci	}
7568c2ecf20Sopenharmony_ci}
7578c2ecf20Sopenharmony_ci
7588c2ecf20Sopenharmony_cistatic void balance_leaf_paste_right_shift(struct tree_balance *tb,
7598c2ecf20Sopenharmony_ci				     struct item_head * const ih,
7608c2ecf20Sopenharmony_ci				     const char * const body)
7618c2ecf20Sopenharmony_ci{
7628c2ecf20Sopenharmony_ci	struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path);
7638c2ecf20Sopenharmony_ci	int n_shift, n_rem, r_zeroes_number, version;
7648c2ecf20Sopenharmony_ci	unsigned long temp_rem;
7658c2ecf20Sopenharmony_ci	const char *r_body;
7668c2ecf20Sopenharmony_ci	struct buffer_info bi;
7678c2ecf20Sopenharmony_ci
7688c2ecf20Sopenharmony_ci	/* we append to directory item */
7698c2ecf20Sopenharmony_ci	if (is_direntry_le_ih(item_head(tbS0, tb->item_pos))) {
7708c2ecf20Sopenharmony_ci		balance_leaf_paste_right_shift_dirent(tb, ih, body);
7718c2ecf20Sopenharmony_ci		return;
7728c2ecf20Sopenharmony_ci	}
7738c2ecf20Sopenharmony_ci
7748c2ecf20Sopenharmony_ci	/* regular object */
7758c2ecf20Sopenharmony_ci
7768c2ecf20Sopenharmony_ci	/*
7778c2ecf20Sopenharmony_ci	 * Calculate number of bytes which must be shifted
7788c2ecf20Sopenharmony_ci	 * from appended item
7798c2ecf20Sopenharmony_ci	 */
7808c2ecf20Sopenharmony_ci	n_shift = tb->rbytes - tb->insert_size[0];
7818c2ecf20Sopenharmony_ci	if (n_shift < 0)
7828c2ecf20Sopenharmony_ci		n_shift = 0;
7838c2ecf20Sopenharmony_ci
7848c2ecf20Sopenharmony_ci	RFALSE(tb->pos_in_item != ih_item_len(item_head(tbS0, tb->item_pos)),
7858c2ecf20Sopenharmony_ci	       "PAP-12155: invalid position to paste. ih_item_len=%d, "
7868c2ecf20Sopenharmony_ci	       "pos_in_item=%d", tb->pos_in_item,
7878c2ecf20Sopenharmony_ci	       ih_item_len(item_head(tbS0, tb->item_pos)));
7888c2ecf20Sopenharmony_ci
7898c2ecf20Sopenharmony_ci	leaf_shift_right(tb, tb->rnum[0], n_shift);
7908c2ecf20Sopenharmony_ci
7918c2ecf20Sopenharmony_ci	/*
7928c2ecf20Sopenharmony_ci	 * Calculate number of bytes which must remain in body
7938c2ecf20Sopenharmony_ci	 * after appending to R[0]
7948c2ecf20Sopenharmony_ci	 */
7958c2ecf20Sopenharmony_ci	n_rem = tb->insert_size[0] - tb->rbytes;
7968c2ecf20Sopenharmony_ci	if (n_rem < 0)
7978c2ecf20Sopenharmony_ci		n_rem = 0;
7988c2ecf20Sopenharmony_ci
7998c2ecf20Sopenharmony_ci	temp_rem = n_rem;
8008c2ecf20Sopenharmony_ci
8018c2ecf20Sopenharmony_ci	version = ih_version(item_head(tb->R[0], 0));
8028c2ecf20Sopenharmony_ci
8038c2ecf20Sopenharmony_ci	if (is_indirect_le_key(version, leaf_key(tb->R[0], 0))) {
8048c2ecf20Sopenharmony_ci		int shift = tb->tb_sb->s_blocksize_bits - UNFM_P_SHIFT;
8058c2ecf20Sopenharmony_ci		temp_rem = n_rem << shift;
8068c2ecf20Sopenharmony_ci	}
8078c2ecf20Sopenharmony_ci
8088c2ecf20Sopenharmony_ci	add_le_key_k_offset(version, leaf_key(tb->R[0], 0), temp_rem);
8098c2ecf20Sopenharmony_ci	add_le_key_k_offset(version, internal_key(tb->CFR[0], tb->rkey[0]),
8108c2ecf20Sopenharmony_ci			    temp_rem);
8118c2ecf20Sopenharmony_ci
8128c2ecf20Sopenharmony_ci	do_balance_mark_internal_dirty(tb, tb->CFR[0], 0);
8138c2ecf20Sopenharmony_ci
8148c2ecf20Sopenharmony_ci	/* Append part of body into R[0] */
8158c2ecf20Sopenharmony_ci	buffer_info_init_right(tb, &bi);
8168c2ecf20Sopenharmony_ci	if (n_rem > tb->zeroes_num) {
8178c2ecf20Sopenharmony_ci		r_zeroes_number = 0;
8188c2ecf20Sopenharmony_ci		r_body = body + n_rem - tb->zeroes_num;
8198c2ecf20Sopenharmony_ci	} else {
8208c2ecf20Sopenharmony_ci		r_body = body;
8218c2ecf20Sopenharmony_ci		r_zeroes_number = tb->zeroes_num - n_rem;
8228c2ecf20Sopenharmony_ci		tb->zeroes_num -= r_zeroes_number;
8238c2ecf20Sopenharmony_ci	}
8248c2ecf20Sopenharmony_ci
8258c2ecf20Sopenharmony_ci	leaf_paste_in_buffer(&bi, 0, n_shift, tb->insert_size[0] - n_rem,
8268c2ecf20Sopenharmony_ci			     r_body, r_zeroes_number);
8278c2ecf20Sopenharmony_ci
8288c2ecf20Sopenharmony_ci	if (is_indirect_le_ih(item_head(tb->R[0], 0)))
8298c2ecf20Sopenharmony_ci		set_ih_free_space(item_head(tb->R[0], 0), 0);
8308c2ecf20Sopenharmony_ci
8318c2ecf20Sopenharmony_ci	tb->insert_size[0] = n_rem;
8328c2ecf20Sopenharmony_ci	if (!n_rem)
8338c2ecf20Sopenharmony_ci		tb->pos_in_item++;
8348c2ecf20Sopenharmony_ci}
8358c2ecf20Sopenharmony_ci
8368c2ecf20Sopenharmony_cistatic void balance_leaf_paste_right_whole(struct tree_balance *tb,
8378c2ecf20Sopenharmony_ci				     struct item_head * const ih,
8388c2ecf20Sopenharmony_ci				     const char * const body)
8398c2ecf20Sopenharmony_ci{
8408c2ecf20Sopenharmony_ci	struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path);
8418c2ecf20Sopenharmony_ci	int n = B_NR_ITEMS(tbS0);
8428c2ecf20Sopenharmony_ci	struct item_head *pasted;
8438c2ecf20Sopenharmony_ci	struct buffer_info bi;
8448c2ecf20Sopenharmony_ci
8458c2ecf20Sopenharmony_ci	buffer_info_init_right(tb, &bi);
8468c2ecf20Sopenharmony_ci	leaf_shift_right(tb, tb->rnum[0], tb->rbytes);
8478c2ecf20Sopenharmony_ci
8488c2ecf20Sopenharmony_ci	/* append item in R[0] */
8498c2ecf20Sopenharmony_ci	if (tb->pos_in_item >= 0) {
8508c2ecf20Sopenharmony_ci		buffer_info_init_right(tb, &bi);
8518c2ecf20Sopenharmony_ci		leaf_paste_in_buffer(&bi, tb->item_pos - n + tb->rnum[0],
8528c2ecf20Sopenharmony_ci				     tb->pos_in_item, tb->insert_size[0], body,
8538c2ecf20Sopenharmony_ci				     tb->zeroes_num);
8548c2ecf20Sopenharmony_ci	}
8558c2ecf20Sopenharmony_ci
8568c2ecf20Sopenharmony_ci	/* paste new entry, if item is directory item */
8578c2ecf20Sopenharmony_ci	pasted = item_head(tb->R[0], tb->item_pos - n + tb->rnum[0]);
8588c2ecf20Sopenharmony_ci	if (is_direntry_le_ih(pasted) && tb->pos_in_item >= 0) {
8598c2ecf20Sopenharmony_ci		leaf_paste_entries(&bi, tb->item_pos - n + tb->rnum[0],
8608c2ecf20Sopenharmony_ci				   tb->pos_in_item, 1,
8618c2ecf20Sopenharmony_ci				   (struct reiserfs_de_head *)body,
8628c2ecf20Sopenharmony_ci				   body + DEH_SIZE, tb->insert_size[0]);
8638c2ecf20Sopenharmony_ci
8648c2ecf20Sopenharmony_ci		if (!tb->pos_in_item) {
8658c2ecf20Sopenharmony_ci
8668c2ecf20Sopenharmony_ci			RFALSE(tb->item_pos - n + tb->rnum[0],
8678c2ecf20Sopenharmony_ci			       "PAP-12165: directory item must be first "
8688c2ecf20Sopenharmony_ci			       "item of node when pasting is in 0th position");
8698c2ecf20Sopenharmony_ci
8708c2ecf20Sopenharmony_ci			/* update delimiting keys */
8718c2ecf20Sopenharmony_ci			replace_key(tb, tb->CFR[0], tb->rkey[0], tb->R[0], 0);
8728c2ecf20Sopenharmony_ci		}
8738c2ecf20Sopenharmony_ci	}
8748c2ecf20Sopenharmony_ci
8758c2ecf20Sopenharmony_ci	if (is_indirect_le_ih(pasted))
8768c2ecf20Sopenharmony_ci		set_ih_free_space(pasted, 0);
8778c2ecf20Sopenharmony_ci	tb->zeroes_num = tb->insert_size[0] = 0;
8788c2ecf20Sopenharmony_ci}
8798c2ecf20Sopenharmony_ci
8808c2ecf20Sopenharmony_cistatic void balance_leaf_paste_right(struct tree_balance *tb,
8818c2ecf20Sopenharmony_ci				     struct item_head * const ih,
8828c2ecf20Sopenharmony_ci				     const char * const body)
8838c2ecf20Sopenharmony_ci{
8848c2ecf20Sopenharmony_ci	struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path);
8858c2ecf20Sopenharmony_ci	int n = B_NR_ITEMS(tbS0);
8868c2ecf20Sopenharmony_ci
8878c2ecf20Sopenharmony_ci	/* new item doesn't fall into R[0] */
8888c2ecf20Sopenharmony_ci	if (n - tb->rnum[0] > tb->item_pos) {
8898c2ecf20Sopenharmony_ci		leaf_shift_right(tb, tb->rnum[0], tb->rbytes);
8908c2ecf20Sopenharmony_ci		return;
8918c2ecf20Sopenharmony_ci	}
8928c2ecf20Sopenharmony_ci
8938c2ecf20Sopenharmony_ci	/* pasted item or part of it falls to R[0] */
8948c2ecf20Sopenharmony_ci
8958c2ecf20Sopenharmony_ci	if (tb->item_pos == n - tb->rnum[0] && tb->rbytes != -1)
8968c2ecf20Sopenharmony_ci		/* we must shift the part of the appended item */
8978c2ecf20Sopenharmony_ci		balance_leaf_paste_right_shift(tb, ih, body);
8988c2ecf20Sopenharmony_ci	else
8998c2ecf20Sopenharmony_ci		/* pasted item in whole falls into R[0] */
9008c2ecf20Sopenharmony_ci		balance_leaf_paste_right_whole(tb, ih, body);
9018c2ecf20Sopenharmony_ci}
9028c2ecf20Sopenharmony_ci
9038c2ecf20Sopenharmony_ci/* shift rnum[0] items from S[0] to the right neighbor R[0] */
9048c2ecf20Sopenharmony_cistatic void balance_leaf_right(struct tree_balance *tb,
9058c2ecf20Sopenharmony_ci			       struct item_head * const ih,
9068c2ecf20Sopenharmony_ci			       const char * const body, int flag)
9078c2ecf20Sopenharmony_ci{
9088c2ecf20Sopenharmony_ci	if (tb->rnum[0] <= 0)
9098c2ecf20Sopenharmony_ci		return;
9108c2ecf20Sopenharmony_ci
9118c2ecf20Sopenharmony_ci	BUG_ON(flag != M_INSERT && flag != M_PASTE);
9128c2ecf20Sopenharmony_ci
9138c2ecf20Sopenharmony_ci	if (flag == M_INSERT)
9148c2ecf20Sopenharmony_ci		balance_leaf_insert_right(tb, ih, body);
9158c2ecf20Sopenharmony_ci	else /* M_PASTE */
9168c2ecf20Sopenharmony_ci		balance_leaf_paste_right(tb, ih, body);
9178c2ecf20Sopenharmony_ci}
9188c2ecf20Sopenharmony_ci
9198c2ecf20Sopenharmony_cistatic void balance_leaf_new_nodes_insert(struct tree_balance *tb,
9208c2ecf20Sopenharmony_ci					  struct item_head * const ih,
9218c2ecf20Sopenharmony_ci					  const char * const body,
9228c2ecf20Sopenharmony_ci					  struct item_head *insert_key,
9238c2ecf20Sopenharmony_ci					  struct buffer_head **insert_ptr,
9248c2ecf20Sopenharmony_ci					  int i)
9258c2ecf20Sopenharmony_ci{
9268c2ecf20Sopenharmony_ci	struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path);
9278c2ecf20Sopenharmony_ci	int n = B_NR_ITEMS(tbS0);
9288c2ecf20Sopenharmony_ci	struct buffer_info bi;
9298c2ecf20Sopenharmony_ci	int shift;
9308c2ecf20Sopenharmony_ci
9318c2ecf20Sopenharmony_ci	/* new item or it part don't falls into S_new[i] */
9328c2ecf20Sopenharmony_ci	if (n - tb->snum[i] >= tb->item_pos) {
9338c2ecf20Sopenharmony_ci		leaf_move_items(LEAF_FROM_S_TO_SNEW, tb,
9348c2ecf20Sopenharmony_ci				tb->snum[i], tb->sbytes[i], tb->S_new[i]);
9358c2ecf20Sopenharmony_ci		return;
9368c2ecf20Sopenharmony_ci	}
9378c2ecf20Sopenharmony_ci
9388c2ecf20Sopenharmony_ci	/* new item or it's part falls to first new node S_new[i] */
9398c2ecf20Sopenharmony_ci
9408c2ecf20Sopenharmony_ci	/* part of new item falls into S_new[i] */
9418c2ecf20Sopenharmony_ci	if (tb->item_pos == n - tb->snum[i] + 1 && tb->sbytes[i] != -1) {
9428c2ecf20Sopenharmony_ci		int old_key_comp, old_len, r_zeroes_number;
9438c2ecf20Sopenharmony_ci		const char *r_body;
9448c2ecf20Sopenharmony_ci
9458c2ecf20Sopenharmony_ci		/* Move snum[i]-1 items from S[0] to S_new[i] */
9468c2ecf20Sopenharmony_ci		leaf_move_items(LEAF_FROM_S_TO_SNEW, tb, tb->snum[i] - 1, -1,
9478c2ecf20Sopenharmony_ci				tb->S_new[i]);
9488c2ecf20Sopenharmony_ci
9498c2ecf20Sopenharmony_ci		/* Remember key component and item length */
9508c2ecf20Sopenharmony_ci		old_key_comp = le_ih_k_offset(ih);
9518c2ecf20Sopenharmony_ci		old_len = ih_item_len(ih);
9528c2ecf20Sopenharmony_ci
9538c2ecf20Sopenharmony_ci		/*
9548c2ecf20Sopenharmony_ci		 * Calculate key component and item length to insert
9558c2ecf20Sopenharmony_ci		 * into S_new[i]
9568c2ecf20Sopenharmony_ci		 */
9578c2ecf20Sopenharmony_ci		shift = 0;
9588c2ecf20Sopenharmony_ci		if (is_indirect_le_ih(ih))
9598c2ecf20Sopenharmony_ci			shift = tb->tb_sb->s_blocksize_bits - UNFM_P_SHIFT;
9608c2ecf20Sopenharmony_ci		set_le_ih_k_offset(ih,
9618c2ecf20Sopenharmony_ci				   le_ih_k_offset(ih) +
9628c2ecf20Sopenharmony_ci				   ((old_len - tb->sbytes[i]) << shift));
9638c2ecf20Sopenharmony_ci
9648c2ecf20Sopenharmony_ci		put_ih_item_len(ih, tb->sbytes[i]);
9658c2ecf20Sopenharmony_ci
9668c2ecf20Sopenharmony_ci		/* Insert part of the item into S_new[i] before 0-th item */
9678c2ecf20Sopenharmony_ci		buffer_info_init_bh(tb, &bi, tb->S_new[i]);
9688c2ecf20Sopenharmony_ci
9698c2ecf20Sopenharmony_ci		if ((old_len - tb->sbytes[i]) > tb->zeroes_num) {
9708c2ecf20Sopenharmony_ci			r_zeroes_number = 0;
9718c2ecf20Sopenharmony_ci			r_body = body + (old_len - tb->sbytes[i]) -
9728c2ecf20Sopenharmony_ci					 tb->zeroes_num;
9738c2ecf20Sopenharmony_ci		} else {
9748c2ecf20Sopenharmony_ci			r_body = body;
9758c2ecf20Sopenharmony_ci			r_zeroes_number = tb->zeroes_num - (old_len -
9768c2ecf20Sopenharmony_ci					  tb->sbytes[i]);
9778c2ecf20Sopenharmony_ci			tb->zeroes_num -= r_zeroes_number;
9788c2ecf20Sopenharmony_ci		}
9798c2ecf20Sopenharmony_ci
9808c2ecf20Sopenharmony_ci		leaf_insert_into_buf(&bi, 0, ih, r_body, r_zeroes_number);
9818c2ecf20Sopenharmony_ci
9828c2ecf20Sopenharmony_ci		/*
9838c2ecf20Sopenharmony_ci		 * Calculate key component and item length to
9848c2ecf20Sopenharmony_ci		 * insert into S[i]
9858c2ecf20Sopenharmony_ci		 */
9868c2ecf20Sopenharmony_ci		set_le_ih_k_offset(ih, old_key_comp);
9878c2ecf20Sopenharmony_ci		put_ih_item_len(ih, old_len - tb->sbytes[i]);
9888c2ecf20Sopenharmony_ci		tb->insert_size[0] -= tb->sbytes[i];
9898c2ecf20Sopenharmony_ci	} else {
9908c2ecf20Sopenharmony_ci		/* whole new item falls into S_new[i] */
9918c2ecf20Sopenharmony_ci
9928c2ecf20Sopenharmony_ci		/*
9938c2ecf20Sopenharmony_ci		 * Shift snum[0] - 1 items to S_new[i]
9948c2ecf20Sopenharmony_ci		 * (sbytes[i] of split item)
9958c2ecf20Sopenharmony_ci		 */
9968c2ecf20Sopenharmony_ci		leaf_move_items(LEAF_FROM_S_TO_SNEW, tb,
9978c2ecf20Sopenharmony_ci				tb->snum[i] - 1, tb->sbytes[i], tb->S_new[i]);
9988c2ecf20Sopenharmony_ci
9998c2ecf20Sopenharmony_ci		/* Insert new item into S_new[i] */
10008c2ecf20Sopenharmony_ci		buffer_info_init_bh(tb, &bi, tb->S_new[i]);
10018c2ecf20Sopenharmony_ci		leaf_insert_into_buf(&bi, tb->item_pos - n + tb->snum[i] - 1,
10028c2ecf20Sopenharmony_ci				     ih, body, tb->zeroes_num);
10038c2ecf20Sopenharmony_ci
10048c2ecf20Sopenharmony_ci		tb->zeroes_num = tb->insert_size[0] = 0;
10058c2ecf20Sopenharmony_ci	}
10068c2ecf20Sopenharmony_ci}
10078c2ecf20Sopenharmony_ci
10088c2ecf20Sopenharmony_ci/* we append to directory item */
10098c2ecf20Sopenharmony_cistatic void balance_leaf_new_nodes_paste_dirent(struct tree_balance *tb,
10108c2ecf20Sopenharmony_ci					 struct item_head * const ih,
10118c2ecf20Sopenharmony_ci					 const char * const body,
10128c2ecf20Sopenharmony_ci					 struct item_head *insert_key,
10138c2ecf20Sopenharmony_ci					 struct buffer_head **insert_ptr,
10148c2ecf20Sopenharmony_ci					 int i)
10158c2ecf20Sopenharmony_ci{
10168c2ecf20Sopenharmony_ci	struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path);
10178c2ecf20Sopenharmony_ci	struct item_head *aux_ih = item_head(tbS0, tb->item_pos);
10188c2ecf20Sopenharmony_ci	int entry_count = ih_entry_count(aux_ih);
10198c2ecf20Sopenharmony_ci	struct buffer_info bi;
10208c2ecf20Sopenharmony_ci
10218c2ecf20Sopenharmony_ci	if (entry_count - tb->sbytes[i] < tb->pos_in_item &&
10228c2ecf20Sopenharmony_ci	    tb->pos_in_item <= entry_count) {
10238c2ecf20Sopenharmony_ci		/* new directory entry falls into S_new[i] */
10248c2ecf20Sopenharmony_ci
10258c2ecf20Sopenharmony_ci		RFALSE(!tb->insert_size[0],
10268c2ecf20Sopenharmony_ci		       "PAP-12215: insert_size is already 0");
10278c2ecf20Sopenharmony_ci		RFALSE(tb->sbytes[i] - 1 >= entry_count,
10288c2ecf20Sopenharmony_ci		       "PAP-12220: there are no so much entries (%d), only %d",
10298c2ecf20Sopenharmony_ci		       tb->sbytes[i] - 1, entry_count);
10308c2ecf20Sopenharmony_ci
10318c2ecf20Sopenharmony_ci		/*
10328c2ecf20Sopenharmony_ci		 * Shift snum[i]-1 items in whole.
10338c2ecf20Sopenharmony_ci		 * Shift sbytes[i] directory entries
10348c2ecf20Sopenharmony_ci		 * from directory item number snum[i]
10358c2ecf20Sopenharmony_ci		 */
10368c2ecf20Sopenharmony_ci		leaf_move_items(LEAF_FROM_S_TO_SNEW, tb, tb->snum[i],
10378c2ecf20Sopenharmony_ci				tb->sbytes[i] - 1, tb->S_new[i]);
10388c2ecf20Sopenharmony_ci
10398c2ecf20Sopenharmony_ci		/*
10408c2ecf20Sopenharmony_ci		 * Paste given directory entry to
10418c2ecf20Sopenharmony_ci		 * directory item
10428c2ecf20Sopenharmony_ci		 */
10438c2ecf20Sopenharmony_ci		buffer_info_init_bh(tb, &bi, tb->S_new[i]);
10448c2ecf20Sopenharmony_ci		leaf_paste_in_buffer(&bi, 0, tb->pos_in_item - entry_count +
10458c2ecf20Sopenharmony_ci				     tb->sbytes[i] - 1, tb->insert_size[0],
10468c2ecf20Sopenharmony_ci				     body, tb->zeroes_num);
10478c2ecf20Sopenharmony_ci
10488c2ecf20Sopenharmony_ci		/* paste new directory entry */
10498c2ecf20Sopenharmony_ci		leaf_paste_entries(&bi, 0, tb->pos_in_item - entry_count +
10508c2ecf20Sopenharmony_ci				   tb->sbytes[i] - 1, 1,
10518c2ecf20Sopenharmony_ci				   (struct reiserfs_de_head *) body,
10528c2ecf20Sopenharmony_ci				   body + DEH_SIZE, tb->insert_size[0]);
10538c2ecf20Sopenharmony_ci
10548c2ecf20Sopenharmony_ci		tb->insert_size[0] = 0;
10558c2ecf20Sopenharmony_ci		tb->pos_in_item++;
10568c2ecf20Sopenharmony_ci	} else {
10578c2ecf20Sopenharmony_ci		/* new directory entry doesn't fall into S_new[i] */
10588c2ecf20Sopenharmony_ci		leaf_move_items(LEAF_FROM_S_TO_SNEW, tb, tb->snum[i],
10598c2ecf20Sopenharmony_ci				tb->sbytes[i], tb->S_new[i]);
10608c2ecf20Sopenharmony_ci	}
10618c2ecf20Sopenharmony_ci
10628c2ecf20Sopenharmony_ci}
10638c2ecf20Sopenharmony_ci
10648c2ecf20Sopenharmony_cistatic void balance_leaf_new_nodes_paste_shift(struct tree_balance *tb,
10658c2ecf20Sopenharmony_ci					 struct item_head * const ih,
10668c2ecf20Sopenharmony_ci					 const char * const body,
10678c2ecf20Sopenharmony_ci					 struct item_head *insert_key,
10688c2ecf20Sopenharmony_ci					 struct buffer_head **insert_ptr,
10698c2ecf20Sopenharmony_ci					 int i)
10708c2ecf20Sopenharmony_ci{
10718c2ecf20Sopenharmony_ci	struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path);
10728c2ecf20Sopenharmony_ci	struct item_head *aux_ih = item_head(tbS0, tb->item_pos);
10738c2ecf20Sopenharmony_ci	int n_shift, n_rem, r_zeroes_number, shift;
10748c2ecf20Sopenharmony_ci	const char *r_body;
10758c2ecf20Sopenharmony_ci	struct item_head *tmp;
10768c2ecf20Sopenharmony_ci	struct buffer_info bi;
10778c2ecf20Sopenharmony_ci
10788c2ecf20Sopenharmony_ci	RFALSE(ih, "PAP-12210: ih must be 0");
10798c2ecf20Sopenharmony_ci
10808c2ecf20Sopenharmony_ci	if (is_direntry_le_ih(aux_ih)) {
10818c2ecf20Sopenharmony_ci		balance_leaf_new_nodes_paste_dirent(tb, ih, body, insert_key,
10828c2ecf20Sopenharmony_ci						    insert_ptr, i);
10838c2ecf20Sopenharmony_ci		return;
10848c2ecf20Sopenharmony_ci	}
10858c2ecf20Sopenharmony_ci
10868c2ecf20Sopenharmony_ci	/* regular object */
10878c2ecf20Sopenharmony_ci
10888c2ecf20Sopenharmony_ci
10898c2ecf20Sopenharmony_ci	RFALSE(tb->pos_in_item != ih_item_len(item_head(tbS0, tb->item_pos)) ||
10908c2ecf20Sopenharmony_ci	       tb->insert_size[0] <= 0,
10918c2ecf20Sopenharmony_ci	       "PAP-12225: item too short or insert_size <= 0");
10928c2ecf20Sopenharmony_ci
10938c2ecf20Sopenharmony_ci	/*
10948c2ecf20Sopenharmony_ci	 * Calculate number of bytes which must be shifted from appended item
10958c2ecf20Sopenharmony_ci	 */
10968c2ecf20Sopenharmony_ci	n_shift = tb->sbytes[i] - tb->insert_size[0];
10978c2ecf20Sopenharmony_ci	if (n_shift < 0)
10988c2ecf20Sopenharmony_ci		n_shift = 0;
10998c2ecf20Sopenharmony_ci	leaf_move_items(LEAF_FROM_S_TO_SNEW, tb, tb->snum[i], n_shift,
11008c2ecf20Sopenharmony_ci			tb->S_new[i]);
11018c2ecf20Sopenharmony_ci
11028c2ecf20Sopenharmony_ci	/*
11038c2ecf20Sopenharmony_ci	 * Calculate number of bytes which must remain in body after
11048c2ecf20Sopenharmony_ci	 * append to S_new[i]
11058c2ecf20Sopenharmony_ci	 */
11068c2ecf20Sopenharmony_ci	n_rem = tb->insert_size[0] - tb->sbytes[i];
11078c2ecf20Sopenharmony_ci	if (n_rem < 0)
11088c2ecf20Sopenharmony_ci		n_rem = 0;
11098c2ecf20Sopenharmony_ci
11108c2ecf20Sopenharmony_ci	/* Append part of body into S_new[0] */
11118c2ecf20Sopenharmony_ci	buffer_info_init_bh(tb, &bi, tb->S_new[i]);
11128c2ecf20Sopenharmony_ci	if (n_rem > tb->zeroes_num) {
11138c2ecf20Sopenharmony_ci		r_zeroes_number = 0;
11148c2ecf20Sopenharmony_ci		r_body = body + n_rem - tb->zeroes_num;
11158c2ecf20Sopenharmony_ci	} else {
11168c2ecf20Sopenharmony_ci		r_body = body;
11178c2ecf20Sopenharmony_ci		r_zeroes_number = tb->zeroes_num - n_rem;
11188c2ecf20Sopenharmony_ci		tb->zeroes_num -= r_zeroes_number;
11198c2ecf20Sopenharmony_ci	}
11208c2ecf20Sopenharmony_ci
11218c2ecf20Sopenharmony_ci	leaf_paste_in_buffer(&bi, 0, n_shift, tb->insert_size[0] - n_rem,
11228c2ecf20Sopenharmony_ci			     r_body, r_zeroes_number);
11238c2ecf20Sopenharmony_ci
11248c2ecf20Sopenharmony_ci	tmp = item_head(tb->S_new[i], 0);
11258c2ecf20Sopenharmony_ci	shift = 0;
11268c2ecf20Sopenharmony_ci	if (is_indirect_le_ih(tmp)) {
11278c2ecf20Sopenharmony_ci		set_ih_free_space(tmp, 0);
11288c2ecf20Sopenharmony_ci		shift = tb->tb_sb->s_blocksize_bits - UNFM_P_SHIFT;
11298c2ecf20Sopenharmony_ci	}
11308c2ecf20Sopenharmony_ci	add_le_ih_k_offset(tmp, n_rem << shift);
11318c2ecf20Sopenharmony_ci
11328c2ecf20Sopenharmony_ci	tb->insert_size[0] = n_rem;
11338c2ecf20Sopenharmony_ci	if (!n_rem)
11348c2ecf20Sopenharmony_ci		tb->pos_in_item++;
11358c2ecf20Sopenharmony_ci}
11368c2ecf20Sopenharmony_ci
11378c2ecf20Sopenharmony_cistatic void balance_leaf_new_nodes_paste_whole(struct tree_balance *tb,
11388c2ecf20Sopenharmony_ci					       struct item_head * const ih,
11398c2ecf20Sopenharmony_ci					       const char * const body,
11408c2ecf20Sopenharmony_ci					       struct item_head *insert_key,
11418c2ecf20Sopenharmony_ci					       struct buffer_head **insert_ptr,
11428c2ecf20Sopenharmony_ci					       int i)
11438c2ecf20Sopenharmony_ci
11448c2ecf20Sopenharmony_ci{
11458c2ecf20Sopenharmony_ci	struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path);
11468c2ecf20Sopenharmony_ci	int n = B_NR_ITEMS(tbS0);
11478c2ecf20Sopenharmony_ci	int leaf_mi;
11488c2ecf20Sopenharmony_ci	struct item_head *pasted;
11498c2ecf20Sopenharmony_ci	struct buffer_info bi;
11508c2ecf20Sopenharmony_ci
11518c2ecf20Sopenharmony_ci#ifdef CONFIG_REISERFS_CHECK
11528c2ecf20Sopenharmony_ci	struct item_head *ih_check = item_head(tbS0, tb->item_pos);
11538c2ecf20Sopenharmony_ci
11548c2ecf20Sopenharmony_ci	if (!is_direntry_le_ih(ih_check) &&
11558c2ecf20Sopenharmony_ci	    (tb->pos_in_item != ih_item_len(ih_check) ||
11568c2ecf20Sopenharmony_ci	    tb->insert_size[0] <= 0))
11578c2ecf20Sopenharmony_ci		reiserfs_panic(tb->tb_sb,
11588c2ecf20Sopenharmony_ci			     "PAP-12235",
11598c2ecf20Sopenharmony_ci			     "pos_in_item must be equal to ih_item_len");
11608c2ecf20Sopenharmony_ci#endif
11618c2ecf20Sopenharmony_ci
11628c2ecf20Sopenharmony_ci	leaf_mi = leaf_move_items(LEAF_FROM_S_TO_SNEW, tb, tb->snum[i],
11638c2ecf20Sopenharmony_ci				  tb->sbytes[i], tb->S_new[i]);
11648c2ecf20Sopenharmony_ci
11658c2ecf20Sopenharmony_ci	RFALSE(leaf_mi,
11668c2ecf20Sopenharmony_ci	       "PAP-12240: unexpected value returned by leaf_move_items (%d)",
11678c2ecf20Sopenharmony_ci	       leaf_mi);
11688c2ecf20Sopenharmony_ci
11698c2ecf20Sopenharmony_ci	/* paste into item */
11708c2ecf20Sopenharmony_ci	buffer_info_init_bh(tb, &bi, tb->S_new[i]);
11718c2ecf20Sopenharmony_ci	leaf_paste_in_buffer(&bi, tb->item_pos - n + tb->snum[i],
11728c2ecf20Sopenharmony_ci			     tb->pos_in_item, tb->insert_size[0],
11738c2ecf20Sopenharmony_ci			     body, tb->zeroes_num);
11748c2ecf20Sopenharmony_ci
11758c2ecf20Sopenharmony_ci	pasted = item_head(tb->S_new[i], tb->item_pos - n +
11768c2ecf20Sopenharmony_ci			   tb->snum[i]);
11778c2ecf20Sopenharmony_ci	if (is_direntry_le_ih(pasted))
11788c2ecf20Sopenharmony_ci		leaf_paste_entries(&bi, tb->item_pos - n + tb->snum[i],
11798c2ecf20Sopenharmony_ci				   tb->pos_in_item, 1,
11808c2ecf20Sopenharmony_ci				   (struct reiserfs_de_head *)body,
11818c2ecf20Sopenharmony_ci				   body + DEH_SIZE, tb->insert_size[0]);
11828c2ecf20Sopenharmony_ci
11838c2ecf20Sopenharmony_ci	/* if we paste to indirect item update ih_free_space */
11848c2ecf20Sopenharmony_ci	if (is_indirect_le_ih(pasted))
11858c2ecf20Sopenharmony_ci		set_ih_free_space(pasted, 0);
11868c2ecf20Sopenharmony_ci
11878c2ecf20Sopenharmony_ci	tb->zeroes_num = tb->insert_size[0] = 0;
11888c2ecf20Sopenharmony_ci
11898c2ecf20Sopenharmony_ci}
11908c2ecf20Sopenharmony_cistatic void balance_leaf_new_nodes_paste(struct tree_balance *tb,
11918c2ecf20Sopenharmony_ci					 struct item_head * const ih,
11928c2ecf20Sopenharmony_ci					 const char * const body,
11938c2ecf20Sopenharmony_ci					 struct item_head *insert_key,
11948c2ecf20Sopenharmony_ci					 struct buffer_head **insert_ptr,
11958c2ecf20Sopenharmony_ci					 int i)
11968c2ecf20Sopenharmony_ci{
11978c2ecf20Sopenharmony_ci	struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path);
11988c2ecf20Sopenharmony_ci	int n = B_NR_ITEMS(tbS0);
11998c2ecf20Sopenharmony_ci
12008c2ecf20Sopenharmony_ci	/* pasted item doesn't fall into S_new[i] */
12018c2ecf20Sopenharmony_ci	if (n - tb->snum[i] > tb->item_pos) {
12028c2ecf20Sopenharmony_ci		leaf_move_items(LEAF_FROM_S_TO_SNEW, tb,
12038c2ecf20Sopenharmony_ci				tb->snum[i], tb->sbytes[i], tb->S_new[i]);
12048c2ecf20Sopenharmony_ci		return;
12058c2ecf20Sopenharmony_ci	}
12068c2ecf20Sopenharmony_ci
12078c2ecf20Sopenharmony_ci	/* pasted item or part if it falls to S_new[i] */
12088c2ecf20Sopenharmony_ci
12098c2ecf20Sopenharmony_ci	if (tb->item_pos == n - tb->snum[i] && tb->sbytes[i] != -1)
12108c2ecf20Sopenharmony_ci		/* we must shift part of the appended item */
12118c2ecf20Sopenharmony_ci		balance_leaf_new_nodes_paste_shift(tb, ih, body, insert_key,
12128c2ecf20Sopenharmony_ci						   insert_ptr, i);
12138c2ecf20Sopenharmony_ci	else
12148c2ecf20Sopenharmony_ci		/* item falls wholly into S_new[i] */
12158c2ecf20Sopenharmony_ci		balance_leaf_new_nodes_paste_whole(tb, ih, body, insert_key,
12168c2ecf20Sopenharmony_ci						   insert_ptr, i);
12178c2ecf20Sopenharmony_ci}
12188c2ecf20Sopenharmony_ci
12198c2ecf20Sopenharmony_ci/* Fill new nodes that appear in place of S[0] */
12208c2ecf20Sopenharmony_cistatic void balance_leaf_new_nodes(struct tree_balance *tb,
12218c2ecf20Sopenharmony_ci				   struct item_head * const ih,
12228c2ecf20Sopenharmony_ci				   const char * const body,
12238c2ecf20Sopenharmony_ci				   struct item_head *insert_key,
12248c2ecf20Sopenharmony_ci				   struct buffer_head **insert_ptr,
12258c2ecf20Sopenharmony_ci				   int flag)
12268c2ecf20Sopenharmony_ci{
12278c2ecf20Sopenharmony_ci	int i;
12288c2ecf20Sopenharmony_ci	for (i = tb->blknum[0] - 2; i >= 0; i--) {
12298c2ecf20Sopenharmony_ci		BUG_ON(flag != M_INSERT && flag != M_PASTE);
12308c2ecf20Sopenharmony_ci
12318c2ecf20Sopenharmony_ci		RFALSE(!tb->snum[i],
12328c2ecf20Sopenharmony_ci		       "PAP-12200: snum[%d] == %d. Must be > 0", i,
12338c2ecf20Sopenharmony_ci		       tb->snum[i]);
12348c2ecf20Sopenharmony_ci
12358c2ecf20Sopenharmony_ci		/* here we shift from S to S_new nodes */
12368c2ecf20Sopenharmony_ci
12378c2ecf20Sopenharmony_ci		tb->S_new[i] = get_FEB(tb);
12388c2ecf20Sopenharmony_ci
12398c2ecf20Sopenharmony_ci		/* initialized block type and tree level */
12408c2ecf20Sopenharmony_ci		set_blkh_level(B_BLK_HEAD(tb->S_new[i]), DISK_LEAF_NODE_LEVEL);
12418c2ecf20Sopenharmony_ci
12428c2ecf20Sopenharmony_ci		if (flag == M_INSERT)
12438c2ecf20Sopenharmony_ci			balance_leaf_new_nodes_insert(tb, ih, body, insert_key,
12448c2ecf20Sopenharmony_ci						      insert_ptr, i);
12458c2ecf20Sopenharmony_ci		else /* M_PASTE */
12468c2ecf20Sopenharmony_ci			balance_leaf_new_nodes_paste(tb, ih, body, insert_key,
12478c2ecf20Sopenharmony_ci						     insert_ptr, i);
12488c2ecf20Sopenharmony_ci
12498c2ecf20Sopenharmony_ci		memcpy(insert_key + i, leaf_key(tb->S_new[i], 0), KEY_SIZE);
12508c2ecf20Sopenharmony_ci		insert_ptr[i] = tb->S_new[i];
12518c2ecf20Sopenharmony_ci
12528c2ecf20Sopenharmony_ci		RFALSE(!buffer_journaled(tb->S_new[i])
12538c2ecf20Sopenharmony_ci		       || buffer_journal_dirty(tb->S_new[i])
12548c2ecf20Sopenharmony_ci		       || buffer_dirty(tb->S_new[i]),
12558c2ecf20Sopenharmony_ci		       "PAP-12247: S_new[%d] : (%b)",
12568c2ecf20Sopenharmony_ci		       i, tb->S_new[i]);
12578c2ecf20Sopenharmony_ci	}
12588c2ecf20Sopenharmony_ci}
12598c2ecf20Sopenharmony_ci
12608c2ecf20Sopenharmony_cistatic void balance_leaf_finish_node_insert(struct tree_balance *tb,
12618c2ecf20Sopenharmony_ci					    struct item_head * const ih,
12628c2ecf20Sopenharmony_ci					    const char * const body)
12638c2ecf20Sopenharmony_ci{
12648c2ecf20Sopenharmony_ci	struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path);
12658c2ecf20Sopenharmony_ci	struct buffer_info bi;
12668c2ecf20Sopenharmony_ci	buffer_info_init_tbS0(tb, &bi);
12678c2ecf20Sopenharmony_ci	leaf_insert_into_buf(&bi, tb->item_pos, ih, body, tb->zeroes_num);
12688c2ecf20Sopenharmony_ci
12698c2ecf20Sopenharmony_ci	/* If we insert the first key change the delimiting key */
12708c2ecf20Sopenharmony_ci	if (tb->item_pos == 0) {
12718c2ecf20Sopenharmony_ci		if (tb->CFL[0])	/* can be 0 in reiserfsck */
12728c2ecf20Sopenharmony_ci			replace_key(tb, tb->CFL[0], tb->lkey[0], tbS0, 0);
12738c2ecf20Sopenharmony_ci
12748c2ecf20Sopenharmony_ci	}
12758c2ecf20Sopenharmony_ci}
12768c2ecf20Sopenharmony_ci
12778c2ecf20Sopenharmony_cistatic void balance_leaf_finish_node_paste_dirent(struct tree_balance *tb,
12788c2ecf20Sopenharmony_ci						  struct item_head * const ih,
12798c2ecf20Sopenharmony_ci						  const char * const body)
12808c2ecf20Sopenharmony_ci{
12818c2ecf20Sopenharmony_ci	struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path);
12828c2ecf20Sopenharmony_ci	struct item_head *pasted = item_head(tbS0, tb->item_pos);
12838c2ecf20Sopenharmony_ci	struct buffer_info bi;
12848c2ecf20Sopenharmony_ci
12858c2ecf20Sopenharmony_ci	if (tb->pos_in_item >= 0 && tb->pos_in_item <= ih_entry_count(pasted)) {
12868c2ecf20Sopenharmony_ci		RFALSE(!tb->insert_size[0],
12878c2ecf20Sopenharmony_ci		       "PAP-12260: insert_size is 0 already");
12888c2ecf20Sopenharmony_ci
12898c2ecf20Sopenharmony_ci		/* prepare space */
12908c2ecf20Sopenharmony_ci		buffer_info_init_tbS0(tb, &bi);
12918c2ecf20Sopenharmony_ci		leaf_paste_in_buffer(&bi, tb->item_pos, tb->pos_in_item,
12928c2ecf20Sopenharmony_ci				     tb->insert_size[0], body, tb->zeroes_num);
12938c2ecf20Sopenharmony_ci
12948c2ecf20Sopenharmony_ci		/* paste entry */
12958c2ecf20Sopenharmony_ci		leaf_paste_entries(&bi, tb->item_pos, tb->pos_in_item, 1,
12968c2ecf20Sopenharmony_ci				   (struct reiserfs_de_head *)body,
12978c2ecf20Sopenharmony_ci				   body + DEH_SIZE, tb->insert_size[0]);
12988c2ecf20Sopenharmony_ci
12998c2ecf20Sopenharmony_ci		if (!tb->item_pos && !tb->pos_in_item) {
13008c2ecf20Sopenharmony_ci			RFALSE(!tb->CFL[0] || !tb->L[0],
13018c2ecf20Sopenharmony_ci			       "PAP-12270: CFL[0]/L[0] must  be specified");
13028c2ecf20Sopenharmony_ci			if (tb->CFL[0])
13038c2ecf20Sopenharmony_ci				replace_key(tb, tb->CFL[0], tb->lkey[0],
13048c2ecf20Sopenharmony_ci					    tbS0, 0);
13058c2ecf20Sopenharmony_ci		}
13068c2ecf20Sopenharmony_ci
13078c2ecf20Sopenharmony_ci		tb->insert_size[0] = 0;
13088c2ecf20Sopenharmony_ci	}
13098c2ecf20Sopenharmony_ci}
13108c2ecf20Sopenharmony_ci
13118c2ecf20Sopenharmony_cistatic void balance_leaf_finish_node_paste(struct tree_balance *tb,
13128c2ecf20Sopenharmony_ci					   struct item_head * const ih,
13138c2ecf20Sopenharmony_ci					   const char * const body)
13148c2ecf20Sopenharmony_ci{
13158c2ecf20Sopenharmony_ci	struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path);
13168c2ecf20Sopenharmony_ci	struct buffer_info bi;
13178c2ecf20Sopenharmony_ci	struct item_head *pasted = item_head(tbS0, tb->item_pos);
13188c2ecf20Sopenharmony_ci
13198c2ecf20Sopenharmony_ci	/* when directory, may be new entry already pasted */
13208c2ecf20Sopenharmony_ci	if (is_direntry_le_ih(pasted)) {
13218c2ecf20Sopenharmony_ci		balance_leaf_finish_node_paste_dirent(tb, ih, body);
13228c2ecf20Sopenharmony_ci		return;
13238c2ecf20Sopenharmony_ci	}
13248c2ecf20Sopenharmony_ci
13258c2ecf20Sopenharmony_ci	/* regular object */
13268c2ecf20Sopenharmony_ci
13278c2ecf20Sopenharmony_ci	if (tb->pos_in_item == ih_item_len(pasted)) {
13288c2ecf20Sopenharmony_ci		RFALSE(tb->insert_size[0] <= 0,
13298c2ecf20Sopenharmony_ci		       "PAP-12275: insert size must not be %d",
13308c2ecf20Sopenharmony_ci		       tb->insert_size[0]);
13318c2ecf20Sopenharmony_ci		buffer_info_init_tbS0(tb, &bi);
13328c2ecf20Sopenharmony_ci		leaf_paste_in_buffer(&bi, tb->item_pos,
13338c2ecf20Sopenharmony_ci				     tb->pos_in_item, tb->insert_size[0], body,
13348c2ecf20Sopenharmony_ci				     tb->zeroes_num);
13358c2ecf20Sopenharmony_ci
13368c2ecf20Sopenharmony_ci		if (is_indirect_le_ih(pasted))
13378c2ecf20Sopenharmony_ci			set_ih_free_space(pasted, 0);
13388c2ecf20Sopenharmony_ci
13398c2ecf20Sopenharmony_ci		tb->insert_size[0] = 0;
13408c2ecf20Sopenharmony_ci	}
13418c2ecf20Sopenharmony_ci#ifdef CONFIG_REISERFS_CHECK
13428c2ecf20Sopenharmony_ci	else if (tb->insert_size[0]) {
13438c2ecf20Sopenharmony_ci		print_cur_tb("12285");
13448c2ecf20Sopenharmony_ci		reiserfs_panic(tb->tb_sb, "PAP-12285",
13458c2ecf20Sopenharmony_ci		    "insert_size must be 0 (%d)", tb->insert_size[0]);
13468c2ecf20Sopenharmony_ci	}
13478c2ecf20Sopenharmony_ci#endif
13488c2ecf20Sopenharmony_ci}
13498c2ecf20Sopenharmony_ci
13508c2ecf20Sopenharmony_ci/*
13518c2ecf20Sopenharmony_ci * if the affected item was not wholly shifted then we
13528c2ecf20Sopenharmony_ci * perform all necessary operations on that part or whole
13538c2ecf20Sopenharmony_ci * of the affected item which remains in S
13548c2ecf20Sopenharmony_ci */
13558c2ecf20Sopenharmony_cistatic void balance_leaf_finish_node(struct tree_balance *tb,
13568c2ecf20Sopenharmony_ci				      struct item_head * const ih,
13578c2ecf20Sopenharmony_ci				      const char * const body, int flag)
13588c2ecf20Sopenharmony_ci{
13598c2ecf20Sopenharmony_ci	/* if we must insert or append into buffer S[0] */
13608c2ecf20Sopenharmony_ci	if (0 <= tb->item_pos && tb->item_pos < tb->s0num) {
13618c2ecf20Sopenharmony_ci		if (flag == M_INSERT)
13628c2ecf20Sopenharmony_ci			balance_leaf_finish_node_insert(tb, ih, body);
13638c2ecf20Sopenharmony_ci		else /* M_PASTE */
13648c2ecf20Sopenharmony_ci			balance_leaf_finish_node_paste(tb, ih, body);
13658c2ecf20Sopenharmony_ci	}
13668c2ecf20Sopenharmony_ci}
13678c2ecf20Sopenharmony_ci
13688c2ecf20Sopenharmony_ci/**
13698c2ecf20Sopenharmony_ci * balance_leaf - reiserfs tree balancing algorithm
13708c2ecf20Sopenharmony_ci * @tb: tree balance state
13718c2ecf20Sopenharmony_ci * @ih: item header of inserted item (little endian)
13728c2ecf20Sopenharmony_ci * @body: body of inserted item or bytes to paste
13738c2ecf20Sopenharmony_ci * @flag: i - insert, d - delete, c - cut, p - paste (see do_balance)
13748c2ecf20Sopenharmony_ci * passed back:
13758c2ecf20Sopenharmony_ci * @insert_key: key to insert new nodes
13768c2ecf20Sopenharmony_ci * @insert_ptr: array of nodes to insert at the next level
13778c2ecf20Sopenharmony_ci *
13788c2ecf20Sopenharmony_ci * In our processing of one level we sometimes determine what must be
13798c2ecf20Sopenharmony_ci * inserted into the next higher level.  This insertion consists of a
13808c2ecf20Sopenharmony_ci * key or two keys and their corresponding pointers.
13818c2ecf20Sopenharmony_ci */
13828c2ecf20Sopenharmony_cistatic int balance_leaf(struct tree_balance *tb, struct item_head *ih,
13838c2ecf20Sopenharmony_ci			const char *body, int flag,
13848c2ecf20Sopenharmony_ci			struct item_head *insert_key,
13858c2ecf20Sopenharmony_ci			struct buffer_head **insert_ptr)
13868c2ecf20Sopenharmony_ci{
13878c2ecf20Sopenharmony_ci	struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path);
13888c2ecf20Sopenharmony_ci
13898c2ecf20Sopenharmony_ci	PROC_INFO_INC(tb->tb_sb, balance_at[0]);
13908c2ecf20Sopenharmony_ci
13918c2ecf20Sopenharmony_ci	/* Make balance in case insert_size[0] < 0 */
13928c2ecf20Sopenharmony_ci	if (tb->insert_size[0] < 0)
13938c2ecf20Sopenharmony_ci		return balance_leaf_when_delete(tb, flag);
13948c2ecf20Sopenharmony_ci
13958c2ecf20Sopenharmony_ci	tb->item_pos = PATH_LAST_POSITION(tb->tb_path),
13968c2ecf20Sopenharmony_ci	tb->pos_in_item = tb->tb_path->pos_in_item,
13978c2ecf20Sopenharmony_ci	tb->zeroes_num = 0;
13988c2ecf20Sopenharmony_ci	if (flag == M_INSERT && !body)
13998c2ecf20Sopenharmony_ci		tb->zeroes_num = ih_item_len(ih);
14008c2ecf20Sopenharmony_ci
14018c2ecf20Sopenharmony_ci	/*
14028c2ecf20Sopenharmony_ci	 * for indirect item pos_in_item is measured in unformatted node
14038c2ecf20Sopenharmony_ci	 * pointers. Recalculate to bytes
14048c2ecf20Sopenharmony_ci	 */
14058c2ecf20Sopenharmony_ci	if (flag != M_INSERT
14068c2ecf20Sopenharmony_ci	    && is_indirect_le_ih(item_head(tbS0, tb->item_pos)))
14078c2ecf20Sopenharmony_ci		tb->pos_in_item *= UNFM_P_SIZE;
14088c2ecf20Sopenharmony_ci
14098c2ecf20Sopenharmony_ci	body += balance_leaf_left(tb, ih, body, flag);
14108c2ecf20Sopenharmony_ci
14118c2ecf20Sopenharmony_ci	/* tb->lnum[0] > 0 */
14128c2ecf20Sopenharmony_ci	/* Calculate new item position */
14138c2ecf20Sopenharmony_ci	tb->item_pos -= (tb->lnum[0] - ((tb->lbytes != -1) ? 1 : 0));
14148c2ecf20Sopenharmony_ci
14158c2ecf20Sopenharmony_ci	balance_leaf_right(tb, ih, body, flag);
14168c2ecf20Sopenharmony_ci
14178c2ecf20Sopenharmony_ci	/* tb->rnum[0] > 0 */
14188c2ecf20Sopenharmony_ci	RFALSE(tb->blknum[0] > 3,
14198c2ecf20Sopenharmony_ci	       "PAP-12180: blknum can not be %d. It must be <= 3", tb->blknum[0]);
14208c2ecf20Sopenharmony_ci	RFALSE(tb->blknum[0] < 0,
14218c2ecf20Sopenharmony_ci	       "PAP-12185: blknum can not be %d. It must be >= 0", tb->blknum[0]);
14228c2ecf20Sopenharmony_ci
14238c2ecf20Sopenharmony_ci	/*
14248c2ecf20Sopenharmony_ci	 * if while adding to a node we discover that it is possible to split
14258c2ecf20Sopenharmony_ci	 * it in two, and merge the left part into the left neighbor and the
14268c2ecf20Sopenharmony_ci	 * right part into the right neighbor, eliminating the node
14278c2ecf20Sopenharmony_ci	 */
14288c2ecf20Sopenharmony_ci	if (tb->blknum[0] == 0) {	/* node S[0] is empty now */
14298c2ecf20Sopenharmony_ci
14308c2ecf20Sopenharmony_ci		RFALSE(!tb->lnum[0] || !tb->rnum[0],
14318c2ecf20Sopenharmony_ci		       "PAP-12190: lnum and rnum must not be zero");
14328c2ecf20Sopenharmony_ci		/*
14338c2ecf20Sopenharmony_ci		 * if insertion was done before 0-th position in R[0], right
14348c2ecf20Sopenharmony_ci		 * delimiting key of the tb->L[0]'s and left delimiting key are
14358c2ecf20Sopenharmony_ci		 * not set correctly
14368c2ecf20Sopenharmony_ci		 */
14378c2ecf20Sopenharmony_ci		if (tb->CFL[0]) {
14388c2ecf20Sopenharmony_ci			if (!tb->CFR[0])
14398c2ecf20Sopenharmony_ci				reiserfs_panic(tb->tb_sb, "vs-12195",
14408c2ecf20Sopenharmony_ci					       "CFR not initialized");
14418c2ecf20Sopenharmony_ci			copy_key(internal_key(tb->CFL[0], tb->lkey[0]),
14428c2ecf20Sopenharmony_ci				 internal_key(tb->CFR[0], tb->rkey[0]));
14438c2ecf20Sopenharmony_ci			do_balance_mark_internal_dirty(tb, tb->CFL[0], 0);
14448c2ecf20Sopenharmony_ci		}
14458c2ecf20Sopenharmony_ci
14468c2ecf20Sopenharmony_ci		reiserfs_invalidate_buffer(tb, tbS0);
14478c2ecf20Sopenharmony_ci		return 0;
14488c2ecf20Sopenharmony_ci	}
14498c2ecf20Sopenharmony_ci
14508c2ecf20Sopenharmony_ci	balance_leaf_new_nodes(tb, ih, body, insert_key, insert_ptr, flag);
14518c2ecf20Sopenharmony_ci
14528c2ecf20Sopenharmony_ci	balance_leaf_finish_node(tb, ih, body, flag);
14538c2ecf20Sopenharmony_ci
14548c2ecf20Sopenharmony_ci#ifdef CONFIG_REISERFS_CHECK
14558c2ecf20Sopenharmony_ci	if (flag == M_PASTE && tb->insert_size[0]) {
14568c2ecf20Sopenharmony_ci		print_cur_tb("12290");
14578c2ecf20Sopenharmony_ci		reiserfs_panic(tb->tb_sb,
14588c2ecf20Sopenharmony_ci			       "PAP-12290", "insert_size is still not 0 (%d)",
14598c2ecf20Sopenharmony_ci			       tb->insert_size[0]);
14608c2ecf20Sopenharmony_ci	}
14618c2ecf20Sopenharmony_ci#endif
14628c2ecf20Sopenharmony_ci
14638c2ecf20Sopenharmony_ci	/* Leaf level of the tree is balanced (end of balance_leaf) */
14648c2ecf20Sopenharmony_ci	return 0;
14658c2ecf20Sopenharmony_ci}
14668c2ecf20Sopenharmony_ci
14678c2ecf20Sopenharmony_ci/* Make empty node */
14688c2ecf20Sopenharmony_civoid make_empty_node(struct buffer_info *bi)
14698c2ecf20Sopenharmony_ci{
14708c2ecf20Sopenharmony_ci	struct block_head *blkh;
14718c2ecf20Sopenharmony_ci
14728c2ecf20Sopenharmony_ci	RFALSE(bi->bi_bh == NULL, "PAP-12295: pointer to the buffer is NULL");
14738c2ecf20Sopenharmony_ci
14748c2ecf20Sopenharmony_ci	blkh = B_BLK_HEAD(bi->bi_bh);
14758c2ecf20Sopenharmony_ci	set_blkh_nr_item(blkh, 0);
14768c2ecf20Sopenharmony_ci	set_blkh_free_space(blkh, MAX_CHILD_SIZE(bi->bi_bh));
14778c2ecf20Sopenharmony_ci
14788c2ecf20Sopenharmony_ci	if (bi->bi_parent)
14798c2ecf20Sopenharmony_ci		B_N_CHILD(bi->bi_parent, bi->bi_position)->dc_size = 0;	/* Endian safe if 0 */
14808c2ecf20Sopenharmony_ci}
14818c2ecf20Sopenharmony_ci
14828c2ecf20Sopenharmony_ci/* Get first empty buffer */
14838c2ecf20Sopenharmony_cistruct buffer_head *get_FEB(struct tree_balance *tb)
14848c2ecf20Sopenharmony_ci{
14858c2ecf20Sopenharmony_ci	int i;
14868c2ecf20Sopenharmony_ci	struct buffer_info bi;
14878c2ecf20Sopenharmony_ci
14888c2ecf20Sopenharmony_ci	for (i = 0; i < MAX_FEB_SIZE; i++)
14898c2ecf20Sopenharmony_ci		if (tb->FEB[i] != NULL)
14908c2ecf20Sopenharmony_ci			break;
14918c2ecf20Sopenharmony_ci
14928c2ecf20Sopenharmony_ci	if (i == MAX_FEB_SIZE)
14938c2ecf20Sopenharmony_ci		reiserfs_panic(tb->tb_sb, "vs-12300", "FEB list is empty");
14948c2ecf20Sopenharmony_ci
14958c2ecf20Sopenharmony_ci	buffer_info_init_bh(tb, &bi, tb->FEB[i]);
14968c2ecf20Sopenharmony_ci	make_empty_node(&bi);
14978c2ecf20Sopenharmony_ci	set_buffer_uptodate(tb->FEB[i]);
14988c2ecf20Sopenharmony_ci	tb->used[i] = tb->FEB[i];
14998c2ecf20Sopenharmony_ci	tb->FEB[i] = NULL;
15008c2ecf20Sopenharmony_ci
15018c2ecf20Sopenharmony_ci	return tb->used[i];
15028c2ecf20Sopenharmony_ci}
15038c2ecf20Sopenharmony_ci
15048c2ecf20Sopenharmony_ci/* This is now used because reiserfs_free_block has to be able to schedule. */
15058c2ecf20Sopenharmony_cistatic void store_thrown(struct tree_balance *tb, struct buffer_head *bh)
15068c2ecf20Sopenharmony_ci{
15078c2ecf20Sopenharmony_ci	int i;
15088c2ecf20Sopenharmony_ci
15098c2ecf20Sopenharmony_ci	if (buffer_dirty(bh))
15108c2ecf20Sopenharmony_ci		reiserfs_warning(tb->tb_sb, "reiserfs-12320",
15118c2ecf20Sopenharmony_ci				 "called with dirty buffer");
15128c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(tb->thrown); i++)
15138c2ecf20Sopenharmony_ci		if (!tb->thrown[i]) {
15148c2ecf20Sopenharmony_ci			tb->thrown[i] = bh;
15158c2ecf20Sopenharmony_ci			get_bh(bh);	/* free_thrown puts this */
15168c2ecf20Sopenharmony_ci			return;
15178c2ecf20Sopenharmony_ci		}
15188c2ecf20Sopenharmony_ci	reiserfs_warning(tb->tb_sb, "reiserfs-12321",
15198c2ecf20Sopenharmony_ci			 "too many thrown buffers");
15208c2ecf20Sopenharmony_ci}
15218c2ecf20Sopenharmony_ci
15228c2ecf20Sopenharmony_cistatic void free_thrown(struct tree_balance *tb)
15238c2ecf20Sopenharmony_ci{
15248c2ecf20Sopenharmony_ci	int i;
15258c2ecf20Sopenharmony_ci	b_blocknr_t blocknr;
15268c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(tb->thrown); i++) {
15278c2ecf20Sopenharmony_ci		if (tb->thrown[i]) {
15288c2ecf20Sopenharmony_ci			blocknr = tb->thrown[i]->b_blocknr;
15298c2ecf20Sopenharmony_ci			if (buffer_dirty(tb->thrown[i]))
15308c2ecf20Sopenharmony_ci				reiserfs_warning(tb->tb_sb, "reiserfs-12322",
15318c2ecf20Sopenharmony_ci						 "called with dirty buffer %d",
15328c2ecf20Sopenharmony_ci						 blocknr);
15338c2ecf20Sopenharmony_ci			brelse(tb->thrown[i]);	/* incremented in store_thrown */
15348c2ecf20Sopenharmony_ci			reiserfs_free_block(tb->transaction_handle, NULL,
15358c2ecf20Sopenharmony_ci					    blocknr, 0);
15368c2ecf20Sopenharmony_ci		}
15378c2ecf20Sopenharmony_ci	}
15388c2ecf20Sopenharmony_ci}
15398c2ecf20Sopenharmony_ci
15408c2ecf20Sopenharmony_civoid reiserfs_invalidate_buffer(struct tree_balance *tb, struct buffer_head *bh)
15418c2ecf20Sopenharmony_ci{
15428c2ecf20Sopenharmony_ci	struct block_head *blkh;
15438c2ecf20Sopenharmony_ci	blkh = B_BLK_HEAD(bh);
15448c2ecf20Sopenharmony_ci	set_blkh_level(blkh, FREE_LEVEL);
15458c2ecf20Sopenharmony_ci	set_blkh_nr_item(blkh, 0);
15468c2ecf20Sopenharmony_ci
15478c2ecf20Sopenharmony_ci	clear_buffer_dirty(bh);
15488c2ecf20Sopenharmony_ci	store_thrown(tb, bh);
15498c2ecf20Sopenharmony_ci}
15508c2ecf20Sopenharmony_ci
15518c2ecf20Sopenharmony_ci/* Replace n_dest'th key in buffer dest by n_src'th key of buffer src.*/
15528c2ecf20Sopenharmony_civoid replace_key(struct tree_balance *tb, struct buffer_head *dest, int n_dest,
15538c2ecf20Sopenharmony_ci		 struct buffer_head *src, int n_src)
15548c2ecf20Sopenharmony_ci{
15558c2ecf20Sopenharmony_ci
15568c2ecf20Sopenharmony_ci	RFALSE(dest == NULL || src == NULL,
15578c2ecf20Sopenharmony_ci	       "vs-12305: source or destination buffer is 0 (src=%p, dest=%p)",
15588c2ecf20Sopenharmony_ci	       src, dest);
15598c2ecf20Sopenharmony_ci	RFALSE(!B_IS_KEYS_LEVEL(dest),
15608c2ecf20Sopenharmony_ci	       "vs-12310: invalid level (%z) for destination buffer. dest must be leaf",
15618c2ecf20Sopenharmony_ci	       dest);
15628c2ecf20Sopenharmony_ci	RFALSE(n_dest < 0 || n_src < 0,
15638c2ecf20Sopenharmony_ci	       "vs-12315: src(%d) or dest(%d) key number < 0", n_src, n_dest);
15648c2ecf20Sopenharmony_ci	RFALSE(n_dest >= B_NR_ITEMS(dest) || n_src >= B_NR_ITEMS(src),
15658c2ecf20Sopenharmony_ci	       "vs-12320: src(%d(%d)) or dest(%d(%d)) key number is too big",
15668c2ecf20Sopenharmony_ci	       n_src, B_NR_ITEMS(src), n_dest, B_NR_ITEMS(dest));
15678c2ecf20Sopenharmony_ci
15688c2ecf20Sopenharmony_ci	if (B_IS_ITEMS_LEVEL(src))
15698c2ecf20Sopenharmony_ci		/* source buffer contains leaf node */
15708c2ecf20Sopenharmony_ci		memcpy(internal_key(dest, n_dest), item_head(src, n_src),
15718c2ecf20Sopenharmony_ci		       KEY_SIZE);
15728c2ecf20Sopenharmony_ci	else
15738c2ecf20Sopenharmony_ci		memcpy(internal_key(dest, n_dest), internal_key(src, n_src),
15748c2ecf20Sopenharmony_ci		       KEY_SIZE);
15758c2ecf20Sopenharmony_ci
15768c2ecf20Sopenharmony_ci	do_balance_mark_internal_dirty(tb, dest, 0);
15778c2ecf20Sopenharmony_ci}
15788c2ecf20Sopenharmony_ci
15798c2ecf20Sopenharmony_ciint get_left_neighbor_position(struct tree_balance *tb, int h)
15808c2ecf20Sopenharmony_ci{
15818c2ecf20Sopenharmony_ci	int Sh_position = PATH_H_POSITION(tb->tb_path, h + 1);
15828c2ecf20Sopenharmony_ci
15838c2ecf20Sopenharmony_ci	RFALSE(PATH_H_PPARENT(tb->tb_path, h) == NULL || tb->FL[h] == NULL,
15848c2ecf20Sopenharmony_ci	       "vs-12325: FL[%d](%p) or F[%d](%p) does not exist",
15858c2ecf20Sopenharmony_ci	       h, tb->FL[h], h, PATH_H_PPARENT(tb->tb_path, h));
15868c2ecf20Sopenharmony_ci
15878c2ecf20Sopenharmony_ci	if (Sh_position == 0)
15888c2ecf20Sopenharmony_ci		return B_NR_ITEMS(tb->FL[h]);
15898c2ecf20Sopenharmony_ci	else
15908c2ecf20Sopenharmony_ci		return Sh_position - 1;
15918c2ecf20Sopenharmony_ci}
15928c2ecf20Sopenharmony_ci
15938c2ecf20Sopenharmony_ciint get_right_neighbor_position(struct tree_balance *tb, int h)
15948c2ecf20Sopenharmony_ci{
15958c2ecf20Sopenharmony_ci	int Sh_position = PATH_H_POSITION(tb->tb_path, h + 1);
15968c2ecf20Sopenharmony_ci
15978c2ecf20Sopenharmony_ci	RFALSE(PATH_H_PPARENT(tb->tb_path, h) == NULL || tb->FR[h] == NULL,
15988c2ecf20Sopenharmony_ci	       "vs-12330: F[%d](%p) or FR[%d](%p) does not exist",
15998c2ecf20Sopenharmony_ci	       h, PATH_H_PPARENT(tb->tb_path, h), h, tb->FR[h]);
16008c2ecf20Sopenharmony_ci
16018c2ecf20Sopenharmony_ci	if (Sh_position == B_NR_ITEMS(PATH_H_PPARENT(tb->tb_path, h)))
16028c2ecf20Sopenharmony_ci		return 0;
16038c2ecf20Sopenharmony_ci	else
16048c2ecf20Sopenharmony_ci		return Sh_position + 1;
16058c2ecf20Sopenharmony_ci}
16068c2ecf20Sopenharmony_ci
16078c2ecf20Sopenharmony_ci#ifdef CONFIG_REISERFS_CHECK
16088c2ecf20Sopenharmony_ci
16098c2ecf20Sopenharmony_ciint is_reusable(struct super_block *s, b_blocknr_t block, int bit_value);
16108c2ecf20Sopenharmony_cistatic void check_internal_node(struct super_block *s, struct buffer_head *bh,
16118c2ecf20Sopenharmony_ci				char *mes)
16128c2ecf20Sopenharmony_ci{
16138c2ecf20Sopenharmony_ci	struct disk_child *dc;
16148c2ecf20Sopenharmony_ci	int i;
16158c2ecf20Sopenharmony_ci
16168c2ecf20Sopenharmony_ci	RFALSE(!bh, "PAP-12336: bh == 0");
16178c2ecf20Sopenharmony_ci
16188c2ecf20Sopenharmony_ci	if (!bh || !B_IS_IN_TREE(bh))
16198c2ecf20Sopenharmony_ci		return;
16208c2ecf20Sopenharmony_ci
16218c2ecf20Sopenharmony_ci	RFALSE(!buffer_dirty(bh) &&
16228c2ecf20Sopenharmony_ci	       !(buffer_journaled(bh) || buffer_journal_dirty(bh)),
16238c2ecf20Sopenharmony_ci	       "PAP-12337: buffer (%b) must be dirty", bh);
16248c2ecf20Sopenharmony_ci	dc = B_N_CHILD(bh, 0);
16258c2ecf20Sopenharmony_ci
16268c2ecf20Sopenharmony_ci	for (i = 0; i <= B_NR_ITEMS(bh); i++, dc++) {
16278c2ecf20Sopenharmony_ci		if (!is_reusable(s, dc_block_number(dc), 1)) {
16288c2ecf20Sopenharmony_ci			print_cur_tb(mes);
16298c2ecf20Sopenharmony_ci			reiserfs_panic(s, "PAP-12338",
16308c2ecf20Sopenharmony_ci				       "invalid child pointer %y in %b",
16318c2ecf20Sopenharmony_ci				       dc, bh);
16328c2ecf20Sopenharmony_ci		}
16338c2ecf20Sopenharmony_ci	}
16348c2ecf20Sopenharmony_ci}
16358c2ecf20Sopenharmony_ci
16368c2ecf20Sopenharmony_cistatic int locked_or_not_in_tree(struct tree_balance *tb,
16378c2ecf20Sopenharmony_ci				  struct buffer_head *bh, char *which)
16388c2ecf20Sopenharmony_ci{
16398c2ecf20Sopenharmony_ci	if ((!buffer_journal_prepared(bh) && buffer_locked(bh)) ||
16408c2ecf20Sopenharmony_ci	    !B_IS_IN_TREE(bh)) {
16418c2ecf20Sopenharmony_ci		reiserfs_warning(tb->tb_sb, "vs-12339", "%s (%b)", which, bh);
16428c2ecf20Sopenharmony_ci		return 1;
16438c2ecf20Sopenharmony_ci	}
16448c2ecf20Sopenharmony_ci	return 0;
16458c2ecf20Sopenharmony_ci}
16468c2ecf20Sopenharmony_ci
16478c2ecf20Sopenharmony_cistatic int check_before_balancing(struct tree_balance *tb)
16488c2ecf20Sopenharmony_ci{
16498c2ecf20Sopenharmony_ci	int retval = 0;
16508c2ecf20Sopenharmony_ci
16518c2ecf20Sopenharmony_ci	if (REISERFS_SB(tb->tb_sb)->cur_tb) {
16528c2ecf20Sopenharmony_ci		reiserfs_panic(tb->tb_sb, "vs-12335", "suspect that schedule "
16538c2ecf20Sopenharmony_ci			       "occurred based on cur_tb not being null at "
16548c2ecf20Sopenharmony_ci			       "this point in code. do_balance cannot properly "
16558c2ecf20Sopenharmony_ci			       "handle concurrent tree accesses on a same "
16568c2ecf20Sopenharmony_ci			       "mount point.");
16578c2ecf20Sopenharmony_ci	}
16588c2ecf20Sopenharmony_ci
16598c2ecf20Sopenharmony_ci	/*
16608c2ecf20Sopenharmony_ci	 * double check that buffers that we will modify are unlocked.
16618c2ecf20Sopenharmony_ci	 * (fix_nodes should already have prepped all of these for us).
16628c2ecf20Sopenharmony_ci	 */
16638c2ecf20Sopenharmony_ci	if (tb->lnum[0]) {
16648c2ecf20Sopenharmony_ci		retval |= locked_or_not_in_tree(tb, tb->L[0], "L[0]");
16658c2ecf20Sopenharmony_ci		retval |= locked_or_not_in_tree(tb, tb->FL[0], "FL[0]");
16668c2ecf20Sopenharmony_ci		retval |= locked_or_not_in_tree(tb, tb->CFL[0], "CFL[0]");
16678c2ecf20Sopenharmony_ci		check_leaf(tb->L[0]);
16688c2ecf20Sopenharmony_ci	}
16698c2ecf20Sopenharmony_ci	if (tb->rnum[0]) {
16708c2ecf20Sopenharmony_ci		retval |= locked_or_not_in_tree(tb, tb->R[0], "R[0]");
16718c2ecf20Sopenharmony_ci		retval |= locked_or_not_in_tree(tb, tb->FR[0], "FR[0]");
16728c2ecf20Sopenharmony_ci		retval |= locked_or_not_in_tree(tb, tb->CFR[0], "CFR[0]");
16738c2ecf20Sopenharmony_ci		check_leaf(tb->R[0]);
16748c2ecf20Sopenharmony_ci	}
16758c2ecf20Sopenharmony_ci	retval |= locked_or_not_in_tree(tb, PATH_PLAST_BUFFER(tb->tb_path),
16768c2ecf20Sopenharmony_ci					"S[0]");
16778c2ecf20Sopenharmony_ci	check_leaf(PATH_PLAST_BUFFER(tb->tb_path));
16788c2ecf20Sopenharmony_ci
16798c2ecf20Sopenharmony_ci	return retval;
16808c2ecf20Sopenharmony_ci}
16818c2ecf20Sopenharmony_ci
16828c2ecf20Sopenharmony_cistatic void check_after_balance_leaf(struct tree_balance *tb)
16838c2ecf20Sopenharmony_ci{
16848c2ecf20Sopenharmony_ci	if (tb->lnum[0]) {
16858c2ecf20Sopenharmony_ci		if (B_FREE_SPACE(tb->L[0]) !=
16868c2ecf20Sopenharmony_ci		    MAX_CHILD_SIZE(tb->L[0]) -
16878c2ecf20Sopenharmony_ci		    dc_size(B_N_CHILD
16888c2ecf20Sopenharmony_ci			    (tb->FL[0], get_left_neighbor_position(tb, 0)))) {
16898c2ecf20Sopenharmony_ci			print_cur_tb("12221");
16908c2ecf20Sopenharmony_ci			reiserfs_panic(tb->tb_sb, "PAP-12355",
16918c2ecf20Sopenharmony_ci				       "shift to left was incorrect");
16928c2ecf20Sopenharmony_ci		}
16938c2ecf20Sopenharmony_ci	}
16948c2ecf20Sopenharmony_ci	if (tb->rnum[0]) {
16958c2ecf20Sopenharmony_ci		if (B_FREE_SPACE(tb->R[0]) !=
16968c2ecf20Sopenharmony_ci		    MAX_CHILD_SIZE(tb->R[0]) -
16978c2ecf20Sopenharmony_ci		    dc_size(B_N_CHILD
16988c2ecf20Sopenharmony_ci			    (tb->FR[0], get_right_neighbor_position(tb, 0)))) {
16998c2ecf20Sopenharmony_ci			print_cur_tb("12222");
17008c2ecf20Sopenharmony_ci			reiserfs_panic(tb->tb_sb, "PAP-12360",
17018c2ecf20Sopenharmony_ci				       "shift to right was incorrect");
17028c2ecf20Sopenharmony_ci		}
17038c2ecf20Sopenharmony_ci	}
17048c2ecf20Sopenharmony_ci	if (PATH_H_PBUFFER(tb->tb_path, 1) &&
17058c2ecf20Sopenharmony_ci	    (B_FREE_SPACE(PATH_H_PBUFFER(tb->tb_path, 0)) !=
17068c2ecf20Sopenharmony_ci	     (MAX_CHILD_SIZE(PATH_H_PBUFFER(tb->tb_path, 0)) -
17078c2ecf20Sopenharmony_ci	      dc_size(B_N_CHILD(PATH_H_PBUFFER(tb->tb_path, 1),
17088c2ecf20Sopenharmony_ci				PATH_H_POSITION(tb->tb_path, 1)))))) {
17098c2ecf20Sopenharmony_ci		int left = B_FREE_SPACE(PATH_H_PBUFFER(tb->tb_path, 0));
17108c2ecf20Sopenharmony_ci		int right = (MAX_CHILD_SIZE(PATH_H_PBUFFER(tb->tb_path, 0)) -
17118c2ecf20Sopenharmony_ci			     dc_size(B_N_CHILD(PATH_H_PBUFFER(tb->tb_path, 1),
17128c2ecf20Sopenharmony_ci					       PATH_H_POSITION(tb->tb_path,
17138c2ecf20Sopenharmony_ci							       1))));
17148c2ecf20Sopenharmony_ci		print_cur_tb("12223");
17158c2ecf20Sopenharmony_ci		reiserfs_warning(tb->tb_sb, "reiserfs-12363",
17168c2ecf20Sopenharmony_ci				 "B_FREE_SPACE (PATH_H_PBUFFER(tb->tb_path,0)) = %d; "
17178c2ecf20Sopenharmony_ci				 "MAX_CHILD_SIZE (%d) - dc_size( %y, %d ) [%d] = %d",
17188c2ecf20Sopenharmony_ci				 left,
17198c2ecf20Sopenharmony_ci				 MAX_CHILD_SIZE(PATH_H_PBUFFER(tb->tb_path, 0)),
17208c2ecf20Sopenharmony_ci				 PATH_H_PBUFFER(tb->tb_path, 1),
17218c2ecf20Sopenharmony_ci				 PATH_H_POSITION(tb->tb_path, 1),
17228c2ecf20Sopenharmony_ci				 dc_size(B_N_CHILD
17238c2ecf20Sopenharmony_ci					 (PATH_H_PBUFFER(tb->tb_path, 1),
17248c2ecf20Sopenharmony_ci					  PATH_H_POSITION(tb->tb_path, 1))),
17258c2ecf20Sopenharmony_ci				 right);
17268c2ecf20Sopenharmony_ci		reiserfs_panic(tb->tb_sb, "PAP-12365", "S is incorrect");
17278c2ecf20Sopenharmony_ci	}
17288c2ecf20Sopenharmony_ci}
17298c2ecf20Sopenharmony_ci
17308c2ecf20Sopenharmony_cistatic void check_leaf_level(struct tree_balance *tb)
17318c2ecf20Sopenharmony_ci{
17328c2ecf20Sopenharmony_ci	check_leaf(tb->L[0]);
17338c2ecf20Sopenharmony_ci	check_leaf(tb->R[0]);
17348c2ecf20Sopenharmony_ci	check_leaf(PATH_PLAST_BUFFER(tb->tb_path));
17358c2ecf20Sopenharmony_ci}
17368c2ecf20Sopenharmony_ci
17378c2ecf20Sopenharmony_cistatic void check_internal_levels(struct tree_balance *tb)
17388c2ecf20Sopenharmony_ci{
17398c2ecf20Sopenharmony_ci	int h;
17408c2ecf20Sopenharmony_ci
17418c2ecf20Sopenharmony_ci	/* check all internal nodes */
17428c2ecf20Sopenharmony_ci	for (h = 1; tb->insert_size[h]; h++) {
17438c2ecf20Sopenharmony_ci		check_internal_node(tb->tb_sb, PATH_H_PBUFFER(tb->tb_path, h),
17448c2ecf20Sopenharmony_ci				    "BAD BUFFER ON PATH");
17458c2ecf20Sopenharmony_ci		if (tb->lnum[h])
17468c2ecf20Sopenharmony_ci			check_internal_node(tb->tb_sb, tb->L[h], "BAD L");
17478c2ecf20Sopenharmony_ci		if (tb->rnum[h])
17488c2ecf20Sopenharmony_ci			check_internal_node(tb->tb_sb, tb->R[h], "BAD R");
17498c2ecf20Sopenharmony_ci	}
17508c2ecf20Sopenharmony_ci
17518c2ecf20Sopenharmony_ci}
17528c2ecf20Sopenharmony_ci
17538c2ecf20Sopenharmony_ci#endif
17548c2ecf20Sopenharmony_ci
17558c2ecf20Sopenharmony_ci/*
17568c2ecf20Sopenharmony_ci * Now we have all of the buffers that must be used in balancing of
17578c2ecf20Sopenharmony_ci * the tree.  We rely on the assumption that schedule() will not occur
17588c2ecf20Sopenharmony_ci * while do_balance works. ( Only interrupt handlers are acceptable.)
17598c2ecf20Sopenharmony_ci * We balance the tree according to the analysis made before this,
17608c2ecf20Sopenharmony_ci * using buffers already obtained.  For SMP support it will someday be
17618c2ecf20Sopenharmony_ci * necessary to add ordered locking of tb.
17628c2ecf20Sopenharmony_ci */
17638c2ecf20Sopenharmony_ci
17648c2ecf20Sopenharmony_ci/*
17658c2ecf20Sopenharmony_ci * Some interesting rules of balancing:
17668c2ecf20Sopenharmony_ci * we delete a maximum of two nodes per level per balancing: we never
17678c2ecf20Sopenharmony_ci * delete R, when we delete two of three nodes L, S, R then we move
17688c2ecf20Sopenharmony_ci * them into R.
17698c2ecf20Sopenharmony_ci *
17708c2ecf20Sopenharmony_ci * we only delete L if we are deleting two nodes, if we delete only
17718c2ecf20Sopenharmony_ci * one node we delete S
17728c2ecf20Sopenharmony_ci *
17738c2ecf20Sopenharmony_ci * if we shift leaves then we shift as much as we can: this is a
17748c2ecf20Sopenharmony_ci * deliberate policy of extremism in node packing which results in
17758c2ecf20Sopenharmony_ci * higher average utilization after repeated random balance operations
17768c2ecf20Sopenharmony_ci * at the cost of more memory copies and more balancing as a result of
17778c2ecf20Sopenharmony_ci * small insertions to full nodes.
17788c2ecf20Sopenharmony_ci *
17798c2ecf20Sopenharmony_ci * if we shift internal nodes we try to evenly balance the node
17808c2ecf20Sopenharmony_ci * utilization, with consequent less balancing at the cost of lower
17818c2ecf20Sopenharmony_ci * utilization.
17828c2ecf20Sopenharmony_ci *
17838c2ecf20Sopenharmony_ci * one could argue that the policy for directories in leaves should be
17848c2ecf20Sopenharmony_ci * that of internal nodes, but we will wait until another day to
17858c2ecf20Sopenharmony_ci * evaluate this....  It would be nice to someday measure and prove
17868c2ecf20Sopenharmony_ci * these assumptions as to what is optimal....
17878c2ecf20Sopenharmony_ci */
17888c2ecf20Sopenharmony_ci
17898c2ecf20Sopenharmony_cistatic inline void do_balance_starts(struct tree_balance *tb)
17908c2ecf20Sopenharmony_ci{
17918c2ecf20Sopenharmony_ci	/* use print_cur_tb() to see initial state of struct tree_balance */
17928c2ecf20Sopenharmony_ci
17938c2ecf20Sopenharmony_ci	/* store_print_tb (tb); */
17948c2ecf20Sopenharmony_ci
17958c2ecf20Sopenharmony_ci	/* do not delete, just comment it out */
17968c2ecf20Sopenharmony_ci	/*
17978c2ecf20Sopenharmony_ci	print_tb(flag, PATH_LAST_POSITION(tb->tb_path),
17988c2ecf20Sopenharmony_ci		 tb->tb_path->pos_in_item, tb, "check");
17998c2ecf20Sopenharmony_ci	*/
18008c2ecf20Sopenharmony_ci	RFALSE(check_before_balancing(tb), "PAP-12340: locked buffers in TB");
18018c2ecf20Sopenharmony_ci#ifdef CONFIG_REISERFS_CHECK
18028c2ecf20Sopenharmony_ci	REISERFS_SB(tb->tb_sb)->cur_tb = tb;
18038c2ecf20Sopenharmony_ci#endif
18048c2ecf20Sopenharmony_ci}
18058c2ecf20Sopenharmony_ci
18068c2ecf20Sopenharmony_cistatic inline void do_balance_completed(struct tree_balance *tb)
18078c2ecf20Sopenharmony_ci{
18088c2ecf20Sopenharmony_ci
18098c2ecf20Sopenharmony_ci#ifdef CONFIG_REISERFS_CHECK
18108c2ecf20Sopenharmony_ci	check_leaf_level(tb);
18118c2ecf20Sopenharmony_ci	check_internal_levels(tb);
18128c2ecf20Sopenharmony_ci	REISERFS_SB(tb->tb_sb)->cur_tb = NULL;
18138c2ecf20Sopenharmony_ci#endif
18148c2ecf20Sopenharmony_ci
18158c2ecf20Sopenharmony_ci	/*
18168c2ecf20Sopenharmony_ci	 * reiserfs_free_block is no longer schedule safe.  So, we need to
18178c2ecf20Sopenharmony_ci	 * put the buffers we want freed on the thrown list during do_balance,
18188c2ecf20Sopenharmony_ci	 * and then free them now
18198c2ecf20Sopenharmony_ci	 */
18208c2ecf20Sopenharmony_ci
18218c2ecf20Sopenharmony_ci	REISERFS_SB(tb->tb_sb)->s_do_balance++;
18228c2ecf20Sopenharmony_ci
18238c2ecf20Sopenharmony_ci	/* release all nodes hold to perform the balancing */
18248c2ecf20Sopenharmony_ci	unfix_nodes(tb);
18258c2ecf20Sopenharmony_ci
18268c2ecf20Sopenharmony_ci	free_thrown(tb);
18278c2ecf20Sopenharmony_ci}
18288c2ecf20Sopenharmony_ci
18298c2ecf20Sopenharmony_ci/*
18308c2ecf20Sopenharmony_ci * do_balance - balance the tree
18318c2ecf20Sopenharmony_ci *
18328c2ecf20Sopenharmony_ci * @tb: tree_balance structure
18338c2ecf20Sopenharmony_ci * @ih: item header of inserted item
18348c2ecf20Sopenharmony_ci * @body: body of inserted item or bytes to paste
18358c2ecf20Sopenharmony_ci * @flag: 'i' - insert, 'd' - delete, 'c' - cut, 'p' paste
18368c2ecf20Sopenharmony_ci *
18378c2ecf20Sopenharmony_ci * Cut means delete part of an item (includes removing an entry from a
18388c2ecf20Sopenharmony_ci * directory).
18398c2ecf20Sopenharmony_ci *
18408c2ecf20Sopenharmony_ci * Delete means delete whole item.
18418c2ecf20Sopenharmony_ci *
18428c2ecf20Sopenharmony_ci * Insert means add a new item into the tree.
18438c2ecf20Sopenharmony_ci *
18448c2ecf20Sopenharmony_ci * Paste means to append to the end of an existing file or to
18458c2ecf20Sopenharmony_ci * insert a directory entry.
18468c2ecf20Sopenharmony_ci */
18478c2ecf20Sopenharmony_civoid do_balance(struct tree_balance *tb, struct item_head *ih,
18488c2ecf20Sopenharmony_ci		const char *body, int flag)
18498c2ecf20Sopenharmony_ci{
18508c2ecf20Sopenharmony_ci	int child_pos;		/* position of a child node in its parent */
18518c2ecf20Sopenharmony_ci	int h;			/* level of the tree being processed */
18528c2ecf20Sopenharmony_ci
18538c2ecf20Sopenharmony_ci	/*
18548c2ecf20Sopenharmony_ci	 * in our processing of one level we sometimes determine what
18558c2ecf20Sopenharmony_ci	 * must be inserted into the next higher level.  This insertion
18568c2ecf20Sopenharmony_ci	 * consists of a key or two keys and their corresponding
18578c2ecf20Sopenharmony_ci	 * pointers
18588c2ecf20Sopenharmony_ci	 */
18598c2ecf20Sopenharmony_ci	struct item_head insert_key[2];
18608c2ecf20Sopenharmony_ci
18618c2ecf20Sopenharmony_ci	/* inserted node-ptrs for the next level */
18628c2ecf20Sopenharmony_ci	struct buffer_head *insert_ptr[2];
18638c2ecf20Sopenharmony_ci
18648c2ecf20Sopenharmony_ci	tb->tb_mode = flag;
18658c2ecf20Sopenharmony_ci	tb->need_balance_dirty = 0;
18668c2ecf20Sopenharmony_ci
18678c2ecf20Sopenharmony_ci	if (FILESYSTEM_CHANGED_TB(tb)) {
18688c2ecf20Sopenharmony_ci		reiserfs_panic(tb->tb_sb, "clm-6000", "fs generation has "
18698c2ecf20Sopenharmony_ci			       "changed");
18708c2ecf20Sopenharmony_ci	}
18718c2ecf20Sopenharmony_ci	/* if we have no real work to do  */
18728c2ecf20Sopenharmony_ci	if (!tb->insert_size[0]) {
18738c2ecf20Sopenharmony_ci		reiserfs_warning(tb->tb_sb, "PAP-12350",
18748c2ecf20Sopenharmony_ci				 "insert_size == 0, mode == %c", flag);
18758c2ecf20Sopenharmony_ci		unfix_nodes(tb);
18768c2ecf20Sopenharmony_ci		return;
18778c2ecf20Sopenharmony_ci	}
18788c2ecf20Sopenharmony_ci
18798c2ecf20Sopenharmony_ci	atomic_inc(&fs_generation(tb->tb_sb));
18808c2ecf20Sopenharmony_ci	do_balance_starts(tb);
18818c2ecf20Sopenharmony_ci
18828c2ecf20Sopenharmony_ci	/*
18838c2ecf20Sopenharmony_ci	 * balance_leaf returns 0 except if combining L R and S into
18848c2ecf20Sopenharmony_ci	 * one node.  see balance_internal() for explanation of this
18858c2ecf20Sopenharmony_ci	 * line of code.
18868c2ecf20Sopenharmony_ci	 */
18878c2ecf20Sopenharmony_ci	child_pos = PATH_H_B_ITEM_ORDER(tb->tb_path, 0) +
18888c2ecf20Sopenharmony_ci	    balance_leaf(tb, ih, body, flag, insert_key, insert_ptr);
18898c2ecf20Sopenharmony_ci
18908c2ecf20Sopenharmony_ci#ifdef CONFIG_REISERFS_CHECK
18918c2ecf20Sopenharmony_ci	check_after_balance_leaf(tb);
18928c2ecf20Sopenharmony_ci#endif
18938c2ecf20Sopenharmony_ci
18948c2ecf20Sopenharmony_ci	/* Balance internal level of the tree. */
18958c2ecf20Sopenharmony_ci	for (h = 1; h < MAX_HEIGHT && tb->insert_size[h]; h++)
18968c2ecf20Sopenharmony_ci		child_pos = balance_internal(tb, h, child_pos, insert_key,
18978c2ecf20Sopenharmony_ci					     insert_ptr);
18988c2ecf20Sopenharmony_ci
18998c2ecf20Sopenharmony_ci	do_balance_completed(tb);
19008c2ecf20Sopenharmony_ci}
1901