162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
362306a36Sopenharmony_ci */
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci#include <linux/time.h>
662306a36Sopenharmony_ci#include <linux/slab.h>
762306a36Sopenharmony_ci#include <linux/string.h>
862306a36Sopenharmony_ci#include "reiserfs.h"
962306a36Sopenharmony_ci#include <linux/buffer_head.h>
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci/*
1262306a36Sopenharmony_ci * To make any changes in the tree we find a node that contains item
1362306a36Sopenharmony_ci * to be changed/deleted or position in the node we insert a new item
1462306a36Sopenharmony_ci * to. We call this node S. To do balancing we need to decide what we
1562306a36Sopenharmony_ci * will shift to left/right neighbor, or to a new node, where new item
1662306a36Sopenharmony_ci * will be etc. To make this analysis simpler we build virtual
1762306a36Sopenharmony_ci * node. Virtual node is an array of items, that will replace items of
1862306a36Sopenharmony_ci * node S. (For instance if we are going to delete an item, virtual
1962306a36Sopenharmony_ci * node does not contain it). Virtual node keeps information about
2062306a36Sopenharmony_ci * item sizes and types, mergeability of first and last items, sizes
2162306a36Sopenharmony_ci * of all entries in directory item. We use this array of items when
2262306a36Sopenharmony_ci * calculating what we can shift to neighbors and how many nodes we
2362306a36Sopenharmony_ci * have to have if we do not any shiftings, if we shift to left/right
2462306a36Sopenharmony_ci * neighbor or to both.
2562306a36Sopenharmony_ci */
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci/*
2862306a36Sopenharmony_ci * Takes item number in virtual node, returns number of item
2962306a36Sopenharmony_ci * that it has in source buffer
3062306a36Sopenharmony_ci */
3162306a36Sopenharmony_cistatic inline int old_item_num(int new_num, int affected_item_num, int mode)
3262306a36Sopenharmony_ci{
3362306a36Sopenharmony_ci	if (mode == M_PASTE || mode == M_CUT || new_num < affected_item_num)
3462306a36Sopenharmony_ci		return new_num;
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci	if (mode == M_INSERT) {
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci		RFALSE(new_num == 0,
3962306a36Sopenharmony_ci		       "vs-8005: for INSERT mode and item number of inserted item");
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci		return new_num - 1;
4262306a36Sopenharmony_ci	}
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci	RFALSE(mode != M_DELETE,
4562306a36Sopenharmony_ci	       "vs-8010: old_item_num: mode must be M_DELETE (mode = \'%c\'",
4662306a36Sopenharmony_ci	       mode);
4762306a36Sopenharmony_ci	/* delete mode */
4862306a36Sopenharmony_ci	return new_num + 1;
4962306a36Sopenharmony_ci}
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_cistatic void create_virtual_node(struct tree_balance *tb, int h)
5262306a36Sopenharmony_ci{
5362306a36Sopenharmony_ci	struct item_head *ih;
5462306a36Sopenharmony_ci	struct virtual_node *vn = tb->tb_vn;
5562306a36Sopenharmony_ci	int new_num;
5662306a36Sopenharmony_ci	struct buffer_head *Sh;	/* this comes from tb->S[h] */
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci	Sh = PATH_H_PBUFFER(tb->tb_path, h);
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci	/* size of changed node */
6162306a36Sopenharmony_ci	vn->vn_size =
6262306a36Sopenharmony_ci	    MAX_CHILD_SIZE(Sh) - B_FREE_SPACE(Sh) + tb->insert_size[h];
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci	/* for internal nodes array if virtual items is not created */
6562306a36Sopenharmony_ci	if (h) {
6662306a36Sopenharmony_ci		vn->vn_nr_item = (vn->vn_size - DC_SIZE) / (DC_SIZE + KEY_SIZE);
6762306a36Sopenharmony_ci		return;
6862306a36Sopenharmony_ci	}
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci	/* number of items in virtual node  */
7162306a36Sopenharmony_ci	vn->vn_nr_item =
7262306a36Sopenharmony_ci	    B_NR_ITEMS(Sh) + ((vn->vn_mode == M_INSERT) ? 1 : 0) -
7362306a36Sopenharmony_ci	    ((vn->vn_mode == M_DELETE) ? 1 : 0);
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci	/* first virtual item */
7662306a36Sopenharmony_ci	vn->vn_vi = (struct virtual_item *)(tb->tb_vn + 1);
7762306a36Sopenharmony_ci	memset(vn->vn_vi, 0, vn->vn_nr_item * sizeof(struct virtual_item));
7862306a36Sopenharmony_ci	vn->vn_free_ptr += vn->vn_nr_item * sizeof(struct virtual_item);
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci	/* first item in the node */
8162306a36Sopenharmony_ci	ih = item_head(Sh, 0);
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci	/* define the mergeability for 0-th item (if it is not being deleted) */
8462306a36Sopenharmony_ci	if (op_is_left_mergeable(&ih->ih_key, Sh->b_size)
8562306a36Sopenharmony_ci	    && (vn->vn_mode != M_DELETE || vn->vn_affected_item_num))
8662306a36Sopenharmony_ci		vn->vn_vi[0].vi_type |= VI_TYPE_LEFT_MERGEABLE;
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci	/*
8962306a36Sopenharmony_ci	 * go through all items that remain in the virtual
9062306a36Sopenharmony_ci	 * node (except for the new (inserted) one)
9162306a36Sopenharmony_ci	 */
9262306a36Sopenharmony_ci	for (new_num = 0; new_num < vn->vn_nr_item; new_num++) {
9362306a36Sopenharmony_ci		int j;
9462306a36Sopenharmony_ci		struct virtual_item *vi = vn->vn_vi + new_num;
9562306a36Sopenharmony_ci		int is_affected =
9662306a36Sopenharmony_ci		    ((new_num != vn->vn_affected_item_num) ? 0 : 1);
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci		if (is_affected && vn->vn_mode == M_INSERT)
9962306a36Sopenharmony_ci			continue;
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci		/* get item number in source node */
10262306a36Sopenharmony_ci		j = old_item_num(new_num, vn->vn_affected_item_num,
10362306a36Sopenharmony_ci				 vn->vn_mode);
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci		vi->vi_item_len += ih_item_len(ih + j) + IH_SIZE;
10662306a36Sopenharmony_ci		vi->vi_ih = ih + j;
10762306a36Sopenharmony_ci		vi->vi_item = ih_item_body(Sh, ih + j);
10862306a36Sopenharmony_ci		vi->vi_uarea = vn->vn_free_ptr;
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ci		/*
11162306a36Sopenharmony_ci		 * FIXME: there is no check that item operation did not
11262306a36Sopenharmony_ci		 * consume too much memory
11362306a36Sopenharmony_ci		 */
11462306a36Sopenharmony_ci		vn->vn_free_ptr +=
11562306a36Sopenharmony_ci		    op_create_vi(vn, vi, is_affected, tb->insert_size[0]);
11662306a36Sopenharmony_ci		if (tb->vn_buf + tb->vn_buf_size < vn->vn_free_ptr)
11762306a36Sopenharmony_ci			reiserfs_panic(tb->tb_sb, "vs-8030",
11862306a36Sopenharmony_ci				       "virtual node space consumed");
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci		if (!is_affected)
12162306a36Sopenharmony_ci			/* this is not being changed */
12262306a36Sopenharmony_ci			continue;
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci		if (vn->vn_mode == M_PASTE || vn->vn_mode == M_CUT) {
12562306a36Sopenharmony_ci			vn->vn_vi[new_num].vi_item_len += tb->insert_size[0];
12662306a36Sopenharmony_ci			/* pointer to data which is going to be pasted */
12762306a36Sopenharmony_ci			vi->vi_new_data = vn->vn_data;
12862306a36Sopenharmony_ci		}
12962306a36Sopenharmony_ci	}
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci	/* virtual inserted item is not defined yet */
13262306a36Sopenharmony_ci	if (vn->vn_mode == M_INSERT) {
13362306a36Sopenharmony_ci		struct virtual_item *vi = vn->vn_vi + vn->vn_affected_item_num;
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci		RFALSE(vn->vn_ins_ih == NULL,
13662306a36Sopenharmony_ci		       "vs-8040: item header of inserted item is not specified");
13762306a36Sopenharmony_ci		vi->vi_item_len = tb->insert_size[0];
13862306a36Sopenharmony_ci		vi->vi_ih = vn->vn_ins_ih;
13962306a36Sopenharmony_ci		vi->vi_item = vn->vn_data;
14062306a36Sopenharmony_ci		vi->vi_uarea = vn->vn_free_ptr;
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_ci		op_create_vi(vn, vi, 0 /*not pasted or cut */ ,
14362306a36Sopenharmony_ci			     tb->insert_size[0]);
14462306a36Sopenharmony_ci	}
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci	/*
14762306a36Sopenharmony_ci	 * set right merge flag we take right delimiting key and
14862306a36Sopenharmony_ci	 * check whether it is a mergeable item
14962306a36Sopenharmony_ci	 */
15062306a36Sopenharmony_ci	if (tb->CFR[0]) {
15162306a36Sopenharmony_ci		struct reiserfs_key *key;
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci		key = internal_key(tb->CFR[0], tb->rkey[0]);
15462306a36Sopenharmony_ci		if (op_is_left_mergeable(key, Sh->b_size)
15562306a36Sopenharmony_ci		    && (vn->vn_mode != M_DELETE
15662306a36Sopenharmony_ci			|| vn->vn_affected_item_num != B_NR_ITEMS(Sh) - 1))
15762306a36Sopenharmony_ci			vn->vn_vi[vn->vn_nr_item - 1].vi_type |=
15862306a36Sopenharmony_ci			    VI_TYPE_RIGHT_MERGEABLE;
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_ci#ifdef CONFIG_REISERFS_CHECK
16162306a36Sopenharmony_ci		if (op_is_left_mergeable(key, Sh->b_size) &&
16262306a36Sopenharmony_ci		    !(vn->vn_mode != M_DELETE
16362306a36Sopenharmony_ci		      || vn->vn_affected_item_num != B_NR_ITEMS(Sh) - 1)) {
16462306a36Sopenharmony_ci			/*
16562306a36Sopenharmony_ci			 * we delete last item and it could be merged
16662306a36Sopenharmony_ci			 * with right neighbor's first item
16762306a36Sopenharmony_ci			 */
16862306a36Sopenharmony_ci			if (!
16962306a36Sopenharmony_ci			    (B_NR_ITEMS(Sh) == 1
17062306a36Sopenharmony_ci			     && is_direntry_le_ih(item_head(Sh, 0))
17162306a36Sopenharmony_ci			     && ih_entry_count(item_head(Sh, 0)) == 1)) {
17262306a36Sopenharmony_ci				/*
17362306a36Sopenharmony_ci				 * node contains more than 1 item, or item
17462306a36Sopenharmony_ci				 * is not directory item, or this item
17562306a36Sopenharmony_ci				 * contains more than 1 entry
17662306a36Sopenharmony_ci				 */
17762306a36Sopenharmony_ci				print_block(Sh, 0, -1, -1);
17862306a36Sopenharmony_ci				reiserfs_panic(tb->tb_sb, "vs-8045",
17962306a36Sopenharmony_ci					       "rdkey %k, affected item==%d "
18062306a36Sopenharmony_ci					       "(mode==%c) Must be %c",
18162306a36Sopenharmony_ci					       key, vn->vn_affected_item_num,
18262306a36Sopenharmony_ci					       vn->vn_mode, M_DELETE);
18362306a36Sopenharmony_ci			}
18462306a36Sopenharmony_ci		}
18562306a36Sopenharmony_ci#endif
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ci	}
18862306a36Sopenharmony_ci}
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_ci/*
19162306a36Sopenharmony_ci * Using virtual node check, how many items can be
19262306a36Sopenharmony_ci * shifted to left neighbor
19362306a36Sopenharmony_ci */
19462306a36Sopenharmony_cistatic void check_left(struct tree_balance *tb, int h, int cur_free)
19562306a36Sopenharmony_ci{
19662306a36Sopenharmony_ci	int i;
19762306a36Sopenharmony_ci	struct virtual_node *vn = tb->tb_vn;
19862306a36Sopenharmony_ci	struct virtual_item *vi;
19962306a36Sopenharmony_ci	int d_size, ih_size;
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_ci	RFALSE(cur_free < 0, "vs-8050: cur_free (%d) < 0", cur_free);
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_ci	/* internal level */
20462306a36Sopenharmony_ci	if (h > 0) {
20562306a36Sopenharmony_ci		tb->lnum[h] = cur_free / (DC_SIZE + KEY_SIZE);
20662306a36Sopenharmony_ci		return;
20762306a36Sopenharmony_ci	}
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci	/* leaf level */
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_ci	if (!cur_free || !vn->vn_nr_item) {
21262306a36Sopenharmony_ci		/* no free space or nothing to move */
21362306a36Sopenharmony_ci		tb->lnum[h] = 0;
21462306a36Sopenharmony_ci		tb->lbytes = -1;
21562306a36Sopenharmony_ci		return;
21662306a36Sopenharmony_ci	}
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci	RFALSE(!PATH_H_PPARENT(tb->tb_path, 0),
21962306a36Sopenharmony_ci	       "vs-8055: parent does not exist or invalid");
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ci	vi = vn->vn_vi;
22262306a36Sopenharmony_ci	if ((unsigned int)cur_free >=
22362306a36Sopenharmony_ci	    (vn->vn_size -
22462306a36Sopenharmony_ci	     ((vi->vi_type & VI_TYPE_LEFT_MERGEABLE) ? IH_SIZE : 0))) {
22562306a36Sopenharmony_ci		/* all contents of S[0] fits into L[0] */
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_ci		RFALSE(vn->vn_mode == M_INSERT || vn->vn_mode == M_PASTE,
22862306a36Sopenharmony_ci		       "vs-8055: invalid mode or balance condition failed");
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_ci		tb->lnum[0] = vn->vn_nr_item;
23162306a36Sopenharmony_ci		tb->lbytes = -1;
23262306a36Sopenharmony_ci		return;
23362306a36Sopenharmony_ci	}
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_ci	d_size = 0, ih_size = IH_SIZE;
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_ci	/* first item may be merge with last item in left neighbor */
23862306a36Sopenharmony_ci	if (vi->vi_type & VI_TYPE_LEFT_MERGEABLE)
23962306a36Sopenharmony_ci		d_size = -((int)IH_SIZE), ih_size = 0;
24062306a36Sopenharmony_ci
24162306a36Sopenharmony_ci	tb->lnum[0] = 0;
24262306a36Sopenharmony_ci	for (i = 0; i < vn->vn_nr_item;
24362306a36Sopenharmony_ci	     i++, ih_size = IH_SIZE, d_size = 0, vi++) {
24462306a36Sopenharmony_ci		d_size += vi->vi_item_len;
24562306a36Sopenharmony_ci		if (cur_free >= d_size) {
24662306a36Sopenharmony_ci			/* the item can be shifted entirely */
24762306a36Sopenharmony_ci			cur_free -= d_size;
24862306a36Sopenharmony_ci			tb->lnum[0]++;
24962306a36Sopenharmony_ci			continue;
25062306a36Sopenharmony_ci		}
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_ci		/* the item cannot be shifted entirely, try to split it */
25362306a36Sopenharmony_ci		/*
25462306a36Sopenharmony_ci		 * check whether L[0] can hold ih and at least one byte
25562306a36Sopenharmony_ci		 * of the item body
25662306a36Sopenharmony_ci		 */
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_ci		/* cannot shift even a part of the current item */
25962306a36Sopenharmony_ci		if (cur_free <= ih_size) {
26062306a36Sopenharmony_ci			tb->lbytes = -1;
26162306a36Sopenharmony_ci			return;
26262306a36Sopenharmony_ci		}
26362306a36Sopenharmony_ci		cur_free -= ih_size;
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_ci		tb->lbytes = op_check_left(vi, cur_free, 0, 0);
26662306a36Sopenharmony_ci		if (tb->lbytes != -1)
26762306a36Sopenharmony_ci			/* count partially shifted item */
26862306a36Sopenharmony_ci			tb->lnum[0]++;
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_ci		break;
27162306a36Sopenharmony_ci	}
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_ci	return;
27462306a36Sopenharmony_ci}
27562306a36Sopenharmony_ci
27662306a36Sopenharmony_ci/*
27762306a36Sopenharmony_ci * Using virtual node check, how many items can be
27862306a36Sopenharmony_ci * shifted to right neighbor
27962306a36Sopenharmony_ci */
28062306a36Sopenharmony_cistatic void check_right(struct tree_balance *tb, int h, int cur_free)
28162306a36Sopenharmony_ci{
28262306a36Sopenharmony_ci	int i;
28362306a36Sopenharmony_ci	struct virtual_node *vn = tb->tb_vn;
28462306a36Sopenharmony_ci	struct virtual_item *vi;
28562306a36Sopenharmony_ci	int d_size, ih_size;
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci	RFALSE(cur_free < 0, "vs-8070: cur_free < 0");
28862306a36Sopenharmony_ci
28962306a36Sopenharmony_ci	/* internal level */
29062306a36Sopenharmony_ci	if (h > 0) {
29162306a36Sopenharmony_ci		tb->rnum[h] = cur_free / (DC_SIZE + KEY_SIZE);
29262306a36Sopenharmony_ci		return;
29362306a36Sopenharmony_ci	}
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_ci	/* leaf level */
29662306a36Sopenharmony_ci
29762306a36Sopenharmony_ci	if (!cur_free || !vn->vn_nr_item) {
29862306a36Sopenharmony_ci		/* no free space  */
29962306a36Sopenharmony_ci		tb->rnum[h] = 0;
30062306a36Sopenharmony_ci		tb->rbytes = -1;
30162306a36Sopenharmony_ci		return;
30262306a36Sopenharmony_ci	}
30362306a36Sopenharmony_ci
30462306a36Sopenharmony_ci	RFALSE(!PATH_H_PPARENT(tb->tb_path, 0),
30562306a36Sopenharmony_ci	       "vs-8075: parent does not exist or invalid");
30662306a36Sopenharmony_ci
30762306a36Sopenharmony_ci	vi = vn->vn_vi + vn->vn_nr_item - 1;
30862306a36Sopenharmony_ci	if ((unsigned int)cur_free >=
30962306a36Sopenharmony_ci	    (vn->vn_size -
31062306a36Sopenharmony_ci	     ((vi->vi_type & VI_TYPE_RIGHT_MERGEABLE) ? IH_SIZE : 0))) {
31162306a36Sopenharmony_ci		/* all contents of S[0] fits into R[0] */
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_ci		RFALSE(vn->vn_mode == M_INSERT || vn->vn_mode == M_PASTE,
31462306a36Sopenharmony_ci		       "vs-8080: invalid mode or balance condition failed");
31562306a36Sopenharmony_ci
31662306a36Sopenharmony_ci		tb->rnum[h] = vn->vn_nr_item;
31762306a36Sopenharmony_ci		tb->rbytes = -1;
31862306a36Sopenharmony_ci		return;
31962306a36Sopenharmony_ci	}
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_ci	d_size = 0, ih_size = IH_SIZE;
32262306a36Sopenharmony_ci
32362306a36Sopenharmony_ci	/* last item may be merge with first item in right neighbor */
32462306a36Sopenharmony_ci	if (vi->vi_type & VI_TYPE_RIGHT_MERGEABLE)
32562306a36Sopenharmony_ci		d_size = -(int)IH_SIZE, ih_size = 0;
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_ci	tb->rnum[0] = 0;
32862306a36Sopenharmony_ci	for (i = vn->vn_nr_item - 1; i >= 0;
32962306a36Sopenharmony_ci	     i--, d_size = 0, ih_size = IH_SIZE, vi--) {
33062306a36Sopenharmony_ci		d_size += vi->vi_item_len;
33162306a36Sopenharmony_ci		if (cur_free >= d_size) {
33262306a36Sopenharmony_ci			/* the item can be shifted entirely */
33362306a36Sopenharmony_ci			cur_free -= d_size;
33462306a36Sopenharmony_ci			tb->rnum[0]++;
33562306a36Sopenharmony_ci			continue;
33662306a36Sopenharmony_ci		}
33762306a36Sopenharmony_ci
33862306a36Sopenharmony_ci		/*
33962306a36Sopenharmony_ci		 * check whether R[0] can hold ih and at least one
34062306a36Sopenharmony_ci		 * byte of the item body
34162306a36Sopenharmony_ci		 */
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_ci		/* cannot shift even a part of the current item */
34462306a36Sopenharmony_ci		if (cur_free <= ih_size) {
34562306a36Sopenharmony_ci			tb->rbytes = -1;
34662306a36Sopenharmony_ci			return;
34762306a36Sopenharmony_ci		}
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_ci		/*
35062306a36Sopenharmony_ci		 * R[0] can hold the header of the item and at least
35162306a36Sopenharmony_ci		 * one byte of its body
35262306a36Sopenharmony_ci		 */
35362306a36Sopenharmony_ci		cur_free -= ih_size;	/* cur_free is still > 0 */
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_ci		tb->rbytes = op_check_right(vi, cur_free);
35662306a36Sopenharmony_ci		if (tb->rbytes != -1)
35762306a36Sopenharmony_ci			/* count partially shifted item */
35862306a36Sopenharmony_ci			tb->rnum[0]++;
35962306a36Sopenharmony_ci
36062306a36Sopenharmony_ci		break;
36162306a36Sopenharmony_ci	}
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_ci	return;
36462306a36Sopenharmony_ci}
36562306a36Sopenharmony_ci
36662306a36Sopenharmony_ci/*
36762306a36Sopenharmony_ci * from - number of items, which are shifted to left neighbor entirely
36862306a36Sopenharmony_ci * to - number of item, which are shifted to right neighbor entirely
36962306a36Sopenharmony_ci * from_bytes - number of bytes of boundary item (or directory entries)
37062306a36Sopenharmony_ci *              which are shifted to left neighbor
37162306a36Sopenharmony_ci * to_bytes - number of bytes of boundary item (or directory entries)
37262306a36Sopenharmony_ci *            which are shifted to right neighbor
37362306a36Sopenharmony_ci */
37462306a36Sopenharmony_cistatic int get_num_ver(int mode, struct tree_balance *tb, int h,
37562306a36Sopenharmony_ci		       int from, int from_bytes,
37662306a36Sopenharmony_ci		       int to, int to_bytes, short *snum012, int flow)
37762306a36Sopenharmony_ci{
37862306a36Sopenharmony_ci	int i;
37962306a36Sopenharmony_ci	int units;
38062306a36Sopenharmony_ci	struct virtual_node *vn = tb->tb_vn;
38162306a36Sopenharmony_ci	int total_node_size, max_node_size, current_item_size;
38262306a36Sopenharmony_ci	int needed_nodes;
38362306a36Sopenharmony_ci
38462306a36Sopenharmony_ci	/* position of item we start filling node from */
38562306a36Sopenharmony_ci	int start_item;
38662306a36Sopenharmony_ci
38762306a36Sopenharmony_ci	/* position of item we finish filling node by */
38862306a36Sopenharmony_ci	int end_item;
38962306a36Sopenharmony_ci
39062306a36Sopenharmony_ci	/*
39162306a36Sopenharmony_ci	 * number of first bytes (entries for directory) of start_item-th item
39262306a36Sopenharmony_ci	 * we do not include into node that is being filled
39362306a36Sopenharmony_ci	 */
39462306a36Sopenharmony_ci	int start_bytes;
39562306a36Sopenharmony_ci
39662306a36Sopenharmony_ci	/*
39762306a36Sopenharmony_ci	 * number of last bytes (entries for directory) of end_item-th item
39862306a36Sopenharmony_ci	 * we do node include into node that is being filled
39962306a36Sopenharmony_ci	 */
40062306a36Sopenharmony_ci	int end_bytes;
40162306a36Sopenharmony_ci
40262306a36Sopenharmony_ci	/*
40362306a36Sopenharmony_ci	 * these are positions in virtual item of items, that are split
40462306a36Sopenharmony_ci	 * between S[0] and S1new and S1new and S2new
40562306a36Sopenharmony_ci	 */
40662306a36Sopenharmony_ci	int split_item_positions[2];
40762306a36Sopenharmony_ci
40862306a36Sopenharmony_ci	split_item_positions[0] = -1;
40962306a36Sopenharmony_ci	split_item_positions[1] = -1;
41062306a36Sopenharmony_ci
41162306a36Sopenharmony_ci	/*
41262306a36Sopenharmony_ci	 * We only create additional nodes if we are in insert or paste mode
41362306a36Sopenharmony_ci	 * or we are in replace mode at the internal level. If h is 0 and
41462306a36Sopenharmony_ci	 * the mode is M_REPLACE then in fix_nodes we change the mode to
41562306a36Sopenharmony_ci	 * paste or insert before we get here in the code.
41662306a36Sopenharmony_ci	 */
41762306a36Sopenharmony_ci	RFALSE(tb->insert_size[h] < 0 || (mode != M_INSERT && mode != M_PASTE),
41862306a36Sopenharmony_ci	       "vs-8100: insert_size < 0 in overflow");
41962306a36Sopenharmony_ci
42062306a36Sopenharmony_ci	max_node_size = MAX_CHILD_SIZE(PATH_H_PBUFFER(tb->tb_path, h));
42162306a36Sopenharmony_ci
42262306a36Sopenharmony_ci	/*
42362306a36Sopenharmony_ci	 * snum012 [0-2] - number of items, that lay
42462306a36Sopenharmony_ci	 * to S[0], first new node and second new node
42562306a36Sopenharmony_ci	 */
42662306a36Sopenharmony_ci	snum012[3] = -1;	/* s1bytes */
42762306a36Sopenharmony_ci	snum012[4] = -1;	/* s2bytes */
42862306a36Sopenharmony_ci
42962306a36Sopenharmony_ci	/* internal level */
43062306a36Sopenharmony_ci	if (h > 0) {
43162306a36Sopenharmony_ci		i = ((to - from) * (KEY_SIZE + DC_SIZE) + DC_SIZE);
43262306a36Sopenharmony_ci		if (i == max_node_size)
43362306a36Sopenharmony_ci			return 1;
43462306a36Sopenharmony_ci		return (i / max_node_size + 1);
43562306a36Sopenharmony_ci	}
43662306a36Sopenharmony_ci
43762306a36Sopenharmony_ci	/* leaf level */
43862306a36Sopenharmony_ci	needed_nodes = 1;
43962306a36Sopenharmony_ci	total_node_size = 0;
44062306a36Sopenharmony_ci
44162306a36Sopenharmony_ci	/* start from 'from'-th item */
44262306a36Sopenharmony_ci	start_item = from;
44362306a36Sopenharmony_ci	/* skip its first 'start_bytes' units */
44462306a36Sopenharmony_ci	start_bytes = ((from_bytes != -1) ? from_bytes : 0);
44562306a36Sopenharmony_ci
44662306a36Sopenharmony_ci	/* last included item is the 'end_item'-th one */
44762306a36Sopenharmony_ci	end_item = vn->vn_nr_item - to - 1;
44862306a36Sopenharmony_ci	/* do not count last 'end_bytes' units of 'end_item'-th item */
44962306a36Sopenharmony_ci	end_bytes = (to_bytes != -1) ? to_bytes : 0;
45062306a36Sopenharmony_ci
45162306a36Sopenharmony_ci	/*
45262306a36Sopenharmony_ci	 * go through all item beginning from the start_item-th item
45362306a36Sopenharmony_ci	 * and ending by the end_item-th item. Do not count first
45462306a36Sopenharmony_ci	 * 'start_bytes' units of 'start_item'-th item and last
45562306a36Sopenharmony_ci	 * 'end_bytes' of 'end_item'-th item
45662306a36Sopenharmony_ci	 */
45762306a36Sopenharmony_ci	for (i = start_item; i <= end_item; i++) {
45862306a36Sopenharmony_ci		struct virtual_item *vi = vn->vn_vi + i;
45962306a36Sopenharmony_ci		int skip_from_end = ((i == end_item) ? end_bytes : 0);
46062306a36Sopenharmony_ci
46162306a36Sopenharmony_ci		RFALSE(needed_nodes > 3, "vs-8105: too many nodes are needed");
46262306a36Sopenharmony_ci
46362306a36Sopenharmony_ci		/* get size of current item */
46462306a36Sopenharmony_ci		current_item_size = vi->vi_item_len;
46562306a36Sopenharmony_ci
46662306a36Sopenharmony_ci		/*
46762306a36Sopenharmony_ci		 * do not take in calculation head part (from_bytes)
46862306a36Sopenharmony_ci		 * of from-th item
46962306a36Sopenharmony_ci		 */
47062306a36Sopenharmony_ci		current_item_size -=
47162306a36Sopenharmony_ci		    op_part_size(vi, 0 /*from start */ , start_bytes);
47262306a36Sopenharmony_ci
47362306a36Sopenharmony_ci		/* do not take in calculation tail part of last item */
47462306a36Sopenharmony_ci		current_item_size -=
47562306a36Sopenharmony_ci		    op_part_size(vi, 1 /*from end */ , skip_from_end);
47662306a36Sopenharmony_ci
47762306a36Sopenharmony_ci		/* if item fits into current node entierly */
47862306a36Sopenharmony_ci		if (total_node_size + current_item_size <= max_node_size) {
47962306a36Sopenharmony_ci			snum012[needed_nodes - 1]++;
48062306a36Sopenharmony_ci			total_node_size += current_item_size;
48162306a36Sopenharmony_ci			start_bytes = 0;
48262306a36Sopenharmony_ci			continue;
48362306a36Sopenharmony_ci		}
48462306a36Sopenharmony_ci
48562306a36Sopenharmony_ci		/*
48662306a36Sopenharmony_ci		 * virtual item length is longer, than max size of item in
48762306a36Sopenharmony_ci		 * a node. It is impossible for direct item
48862306a36Sopenharmony_ci		 */
48962306a36Sopenharmony_ci		if (current_item_size > max_node_size) {
49062306a36Sopenharmony_ci			RFALSE(is_direct_le_ih(vi->vi_ih),
49162306a36Sopenharmony_ci			       "vs-8110: "
49262306a36Sopenharmony_ci			       "direct item length is %d. It can not be longer than %d",
49362306a36Sopenharmony_ci			       current_item_size, max_node_size);
49462306a36Sopenharmony_ci			/* we will try to split it */
49562306a36Sopenharmony_ci			flow = 1;
49662306a36Sopenharmony_ci		}
49762306a36Sopenharmony_ci
49862306a36Sopenharmony_ci		/* as we do not split items, take new node and continue */
49962306a36Sopenharmony_ci		if (!flow) {
50062306a36Sopenharmony_ci			needed_nodes++;
50162306a36Sopenharmony_ci			i--;
50262306a36Sopenharmony_ci			total_node_size = 0;
50362306a36Sopenharmony_ci			continue;
50462306a36Sopenharmony_ci		}
50562306a36Sopenharmony_ci
50662306a36Sopenharmony_ci		/*
50762306a36Sopenharmony_ci		 * calculate number of item units which fit into node being
50862306a36Sopenharmony_ci		 * filled
50962306a36Sopenharmony_ci		 */
51062306a36Sopenharmony_ci		{
51162306a36Sopenharmony_ci			int free_space;
51262306a36Sopenharmony_ci
51362306a36Sopenharmony_ci			free_space = max_node_size - total_node_size - IH_SIZE;
51462306a36Sopenharmony_ci			units =
51562306a36Sopenharmony_ci			    op_check_left(vi, free_space, start_bytes,
51662306a36Sopenharmony_ci					  skip_from_end);
51762306a36Sopenharmony_ci			/*
51862306a36Sopenharmony_ci			 * nothing fits into current node, take new
51962306a36Sopenharmony_ci			 * node and continue
52062306a36Sopenharmony_ci			 */
52162306a36Sopenharmony_ci			if (units == -1) {
52262306a36Sopenharmony_ci				needed_nodes++, i--, total_node_size = 0;
52362306a36Sopenharmony_ci				continue;
52462306a36Sopenharmony_ci			}
52562306a36Sopenharmony_ci		}
52662306a36Sopenharmony_ci
52762306a36Sopenharmony_ci		/* something fits into the current node */
52862306a36Sopenharmony_ci		start_bytes += units;
52962306a36Sopenharmony_ci		snum012[needed_nodes - 1 + 3] = units;
53062306a36Sopenharmony_ci
53162306a36Sopenharmony_ci		if (needed_nodes > 2)
53262306a36Sopenharmony_ci			reiserfs_warning(tb->tb_sb, "vs-8111",
53362306a36Sopenharmony_ci					 "split_item_position is out of range");
53462306a36Sopenharmony_ci		snum012[needed_nodes - 1]++;
53562306a36Sopenharmony_ci		split_item_positions[needed_nodes - 1] = i;
53662306a36Sopenharmony_ci		needed_nodes++;
53762306a36Sopenharmony_ci		/* continue from the same item with start_bytes != -1 */
53862306a36Sopenharmony_ci		start_item = i;
53962306a36Sopenharmony_ci		i--;
54062306a36Sopenharmony_ci		total_node_size = 0;
54162306a36Sopenharmony_ci	}
54262306a36Sopenharmony_ci
54362306a36Sopenharmony_ci	/*
54462306a36Sopenharmony_ci	 * sum012[4] (if it is not -1) contains number of units of which
54562306a36Sopenharmony_ci	 * are to be in S1new, snum012[3] - to be in S0. They are supposed
54662306a36Sopenharmony_ci	 * to be S1bytes and S2bytes correspondingly, so recalculate
54762306a36Sopenharmony_ci	 */
54862306a36Sopenharmony_ci	if (snum012[4] > 0) {
54962306a36Sopenharmony_ci		int split_item_num;
55062306a36Sopenharmony_ci		int bytes_to_r, bytes_to_l;
55162306a36Sopenharmony_ci		int bytes_to_S1new;
55262306a36Sopenharmony_ci
55362306a36Sopenharmony_ci		split_item_num = split_item_positions[1];
55462306a36Sopenharmony_ci		bytes_to_l =
55562306a36Sopenharmony_ci		    ((from == split_item_num
55662306a36Sopenharmony_ci		      && from_bytes != -1) ? from_bytes : 0);
55762306a36Sopenharmony_ci		bytes_to_r =
55862306a36Sopenharmony_ci		    ((end_item == split_item_num
55962306a36Sopenharmony_ci		      && end_bytes != -1) ? end_bytes : 0);
56062306a36Sopenharmony_ci		bytes_to_S1new =
56162306a36Sopenharmony_ci		    ((split_item_positions[0] ==
56262306a36Sopenharmony_ci		      split_item_positions[1]) ? snum012[3] : 0);
56362306a36Sopenharmony_ci
56462306a36Sopenharmony_ci		/* s2bytes */
56562306a36Sopenharmony_ci		snum012[4] =
56662306a36Sopenharmony_ci		    op_unit_num(&vn->vn_vi[split_item_num]) - snum012[4] -
56762306a36Sopenharmony_ci		    bytes_to_r - bytes_to_l - bytes_to_S1new;
56862306a36Sopenharmony_ci
56962306a36Sopenharmony_ci		if (vn->vn_vi[split_item_num].vi_index != TYPE_DIRENTRY &&
57062306a36Sopenharmony_ci		    vn->vn_vi[split_item_num].vi_index != TYPE_INDIRECT)
57162306a36Sopenharmony_ci			reiserfs_warning(tb->tb_sb, "vs-8115",
57262306a36Sopenharmony_ci					 "not directory or indirect item");
57362306a36Sopenharmony_ci	}
57462306a36Sopenharmony_ci
57562306a36Sopenharmony_ci	/* now we know S2bytes, calculate S1bytes */
57662306a36Sopenharmony_ci	if (snum012[3] > 0) {
57762306a36Sopenharmony_ci		int split_item_num;
57862306a36Sopenharmony_ci		int bytes_to_r, bytes_to_l;
57962306a36Sopenharmony_ci		int bytes_to_S2new;
58062306a36Sopenharmony_ci
58162306a36Sopenharmony_ci		split_item_num = split_item_positions[0];
58262306a36Sopenharmony_ci		bytes_to_l =
58362306a36Sopenharmony_ci		    ((from == split_item_num
58462306a36Sopenharmony_ci		      && from_bytes != -1) ? from_bytes : 0);
58562306a36Sopenharmony_ci		bytes_to_r =
58662306a36Sopenharmony_ci		    ((end_item == split_item_num
58762306a36Sopenharmony_ci		      && end_bytes != -1) ? end_bytes : 0);
58862306a36Sopenharmony_ci		bytes_to_S2new =
58962306a36Sopenharmony_ci		    ((split_item_positions[0] == split_item_positions[1]
59062306a36Sopenharmony_ci		      && snum012[4] != -1) ? snum012[4] : 0);
59162306a36Sopenharmony_ci
59262306a36Sopenharmony_ci		/* s1bytes */
59362306a36Sopenharmony_ci		snum012[3] =
59462306a36Sopenharmony_ci		    op_unit_num(&vn->vn_vi[split_item_num]) - snum012[3] -
59562306a36Sopenharmony_ci		    bytes_to_r - bytes_to_l - bytes_to_S2new;
59662306a36Sopenharmony_ci	}
59762306a36Sopenharmony_ci
59862306a36Sopenharmony_ci	return needed_nodes;
59962306a36Sopenharmony_ci}
60062306a36Sopenharmony_ci
60162306a36Sopenharmony_ci
60262306a36Sopenharmony_ci/*
60362306a36Sopenharmony_ci * Set parameters for balancing.
60462306a36Sopenharmony_ci * Performs write of results of analysis of balancing into structure tb,
60562306a36Sopenharmony_ci * where it will later be used by the functions that actually do the balancing.
60662306a36Sopenharmony_ci * Parameters:
60762306a36Sopenharmony_ci *	tb	tree_balance structure;
60862306a36Sopenharmony_ci *	h	current level of the node;
60962306a36Sopenharmony_ci *	lnum	number of items from S[h] that must be shifted to L[h];
61062306a36Sopenharmony_ci *	rnum	number of items from S[h] that must be shifted to R[h];
61162306a36Sopenharmony_ci *	blk_num	number of blocks that S[h] will be splitted into;
61262306a36Sopenharmony_ci *	s012	number of items that fall into splitted nodes.
61362306a36Sopenharmony_ci *	lbytes	number of bytes which flow to the left neighbor from the
61462306a36Sopenharmony_ci *              item that is not shifted entirely
61562306a36Sopenharmony_ci *	rbytes	number of bytes which flow to the right neighbor from the
61662306a36Sopenharmony_ci *              item that is not shifted entirely
61762306a36Sopenharmony_ci *	s1bytes	number of bytes which flow to the first  new node when
61862306a36Sopenharmony_ci *              S[0] splits (this number is contained in s012 array)
61962306a36Sopenharmony_ci */
62062306a36Sopenharmony_ci
62162306a36Sopenharmony_cistatic void set_parameters(struct tree_balance *tb, int h, int lnum,
62262306a36Sopenharmony_ci			   int rnum, int blk_num, short *s012, int lb, int rb)
62362306a36Sopenharmony_ci{
62462306a36Sopenharmony_ci
62562306a36Sopenharmony_ci	tb->lnum[h] = lnum;
62662306a36Sopenharmony_ci	tb->rnum[h] = rnum;
62762306a36Sopenharmony_ci	tb->blknum[h] = blk_num;
62862306a36Sopenharmony_ci
62962306a36Sopenharmony_ci	/* only for leaf level */
63062306a36Sopenharmony_ci	if (h == 0) {
63162306a36Sopenharmony_ci		if (s012 != NULL) {
63262306a36Sopenharmony_ci			tb->s0num = *s012++;
63362306a36Sopenharmony_ci			tb->snum[0] = *s012++;
63462306a36Sopenharmony_ci			tb->snum[1] = *s012++;
63562306a36Sopenharmony_ci			tb->sbytes[0] = *s012++;
63662306a36Sopenharmony_ci			tb->sbytes[1] = *s012;
63762306a36Sopenharmony_ci		}
63862306a36Sopenharmony_ci		tb->lbytes = lb;
63962306a36Sopenharmony_ci		tb->rbytes = rb;
64062306a36Sopenharmony_ci	}
64162306a36Sopenharmony_ci	PROC_INFO_ADD(tb->tb_sb, lnum[h], lnum);
64262306a36Sopenharmony_ci	PROC_INFO_ADD(tb->tb_sb, rnum[h], rnum);
64362306a36Sopenharmony_ci
64462306a36Sopenharmony_ci	PROC_INFO_ADD(tb->tb_sb, lbytes[h], lb);
64562306a36Sopenharmony_ci	PROC_INFO_ADD(tb->tb_sb, rbytes[h], rb);
64662306a36Sopenharmony_ci}
64762306a36Sopenharmony_ci
64862306a36Sopenharmony_ci/*
64962306a36Sopenharmony_ci * check if node disappears if we shift tb->lnum[0] items to left
65062306a36Sopenharmony_ci * neighbor and tb->rnum[0] to the right one.
65162306a36Sopenharmony_ci */
65262306a36Sopenharmony_cistatic int is_leaf_removable(struct tree_balance *tb)
65362306a36Sopenharmony_ci{
65462306a36Sopenharmony_ci	struct virtual_node *vn = tb->tb_vn;
65562306a36Sopenharmony_ci	int to_left, to_right;
65662306a36Sopenharmony_ci	int size;
65762306a36Sopenharmony_ci	int remain_items;
65862306a36Sopenharmony_ci
65962306a36Sopenharmony_ci	/*
66062306a36Sopenharmony_ci	 * number of items that will be shifted to left (right) neighbor
66162306a36Sopenharmony_ci	 * entirely
66262306a36Sopenharmony_ci	 */
66362306a36Sopenharmony_ci	to_left = tb->lnum[0] - ((tb->lbytes != -1) ? 1 : 0);
66462306a36Sopenharmony_ci	to_right = tb->rnum[0] - ((tb->rbytes != -1) ? 1 : 0);
66562306a36Sopenharmony_ci	remain_items = vn->vn_nr_item;
66662306a36Sopenharmony_ci
66762306a36Sopenharmony_ci	/* how many items remain in S[0] after shiftings to neighbors */
66862306a36Sopenharmony_ci	remain_items -= (to_left + to_right);
66962306a36Sopenharmony_ci
67062306a36Sopenharmony_ci	/* all content of node can be shifted to neighbors */
67162306a36Sopenharmony_ci	if (remain_items < 1) {
67262306a36Sopenharmony_ci		set_parameters(tb, 0, to_left, vn->vn_nr_item - to_left, 0,
67362306a36Sopenharmony_ci			       NULL, -1, -1);
67462306a36Sopenharmony_ci		return 1;
67562306a36Sopenharmony_ci	}
67662306a36Sopenharmony_ci
67762306a36Sopenharmony_ci	/* S[0] is not removable */
67862306a36Sopenharmony_ci	if (remain_items > 1 || tb->lbytes == -1 || tb->rbytes == -1)
67962306a36Sopenharmony_ci		return 0;
68062306a36Sopenharmony_ci
68162306a36Sopenharmony_ci	/* check whether we can divide 1 remaining item between neighbors */
68262306a36Sopenharmony_ci
68362306a36Sopenharmony_ci	/* get size of remaining item (in item units) */
68462306a36Sopenharmony_ci	size = op_unit_num(&vn->vn_vi[to_left]);
68562306a36Sopenharmony_ci
68662306a36Sopenharmony_ci	if (tb->lbytes + tb->rbytes >= size) {
68762306a36Sopenharmony_ci		set_parameters(tb, 0, to_left + 1, to_right + 1, 0, NULL,
68862306a36Sopenharmony_ci			       tb->lbytes, -1);
68962306a36Sopenharmony_ci		return 1;
69062306a36Sopenharmony_ci	}
69162306a36Sopenharmony_ci
69262306a36Sopenharmony_ci	return 0;
69362306a36Sopenharmony_ci}
69462306a36Sopenharmony_ci
69562306a36Sopenharmony_ci/* check whether L, S, R can be joined in one node */
69662306a36Sopenharmony_cistatic int are_leaves_removable(struct tree_balance *tb, int lfree, int rfree)
69762306a36Sopenharmony_ci{
69862306a36Sopenharmony_ci	struct virtual_node *vn = tb->tb_vn;
69962306a36Sopenharmony_ci	int ih_size;
70062306a36Sopenharmony_ci	struct buffer_head *S0;
70162306a36Sopenharmony_ci
70262306a36Sopenharmony_ci	S0 = PATH_H_PBUFFER(tb->tb_path, 0);
70362306a36Sopenharmony_ci
70462306a36Sopenharmony_ci	ih_size = 0;
70562306a36Sopenharmony_ci	if (vn->vn_nr_item) {
70662306a36Sopenharmony_ci		if (vn->vn_vi[0].vi_type & VI_TYPE_LEFT_MERGEABLE)
70762306a36Sopenharmony_ci			ih_size += IH_SIZE;
70862306a36Sopenharmony_ci
70962306a36Sopenharmony_ci		if (vn->vn_vi[vn->vn_nr_item - 1].
71062306a36Sopenharmony_ci		    vi_type & VI_TYPE_RIGHT_MERGEABLE)
71162306a36Sopenharmony_ci			ih_size += IH_SIZE;
71262306a36Sopenharmony_ci	} else {
71362306a36Sopenharmony_ci		/* there was only one item and it will be deleted */
71462306a36Sopenharmony_ci		struct item_head *ih;
71562306a36Sopenharmony_ci
71662306a36Sopenharmony_ci		RFALSE(B_NR_ITEMS(S0) != 1,
71762306a36Sopenharmony_ci		       "vs-8125: item number must be 1: it is %d",
71862306a36Sopenharmony_ci		       B_NR_ITEMS(S0));
71962306a36Sopenharmony_ci
72062306a36Sopenharmony_ci		ih = item_head(S0, 0);
72162306a36Sopenharmony_ci		if (tb->CFR[0]
72262306a36Sopenharmony_ci		    && !comp_short_le_keys(&ih->ih_key,
72362306a36Sopenharmony_ci					   internal_key(tb->CFR[0],
72462306a36Sopenharmony_ci							  tb->rkey[0])))
72562306a36Sopenharmony_ci			/*
72662306a36Sopenharmony_ci			 * Directory must be in correct state here: that is
72762306a36Sopenharmony_ci			 * somewhere at the left side should exist first
72862306a36Sopenharmony_ci			 * directory item. But the item being deleted can
72962306a36Sopenharmony_ci			 * not be that first one because its right neighbor
73062306a36Sopenharmony_ci			 * is item of the same directory. (But first item
73162306a36Sopenharmony_ci			 * always gets deleted in last turn). So, neighbors
73262306a36Sopenharmony_ci			 * of deleted item can be merged, so we can save
73362306a36Sopenharmony_ci			 * ih_size
73462306a36Sopenharmony_ci			 */
73562306a36Sopenharmony_ci			if (is_direntry_le_ih(ih)) {
73662306a36Sopenharmony_ci				ih_size = IH_SIZE;
73762306a36Sopenharmony_ci
73862306a36Sopenharmony_ci				/*
73962306a36Sopenharmony_ci				 * we might check that left neighbor exists
74062306a36Sopenharmony_ci				 * and is of the same directory
74162306a36Sopenharmony_ci				 */
74262306a36Sopenharmony_ci				RFALSE(le_ih_k_offset(ih) == DOT_OFFSET,
74362306a36Sopenharmony_ci				       "vs-8130: first directory item can not be removed until directory is not empty");
74462306a36Sopenharmony_ci			}
74562306a36Sopenharmony_ci
74662306a36Sopenharmony_ci	}
74762306a36Sopenharmony_ci
74862306a36Sopenharmony_ci	if (MAX_CHILD_SIZE(S0) + vn->vn_size <= rfree + lfree + ih_size) {
74962306a36Sopenharmony_ci		set_parameters(tb, 0, -1, -1, -1, NULL, -1, -1);
75062306a36Sopenharmony_ci		PROC_INFO_INC(tb->tb_sb, leaves_removable);
75162306a36Sopenharmony_ci		return 1;
75262306a36Sopenharmony_ci	}
75362306a36Sopenharmony_ci	return 0;
75462306a36Sopenharmony_ci
75562306a36Sopenharmony_ci}
75662306a36Sopenharmony_ci
75762306a36Sopenharmony_ci/* when we do not split item, lnum and rnum are numbers of entire items */
75862306a36Sopenharmony_ci#define SET_PAR_SHIFT_LEFT \
75962306a36Sopenharmony_ciif (h)\
76062306a36Sopenharmony_ci{\
76162306a36Sopenharmony_ci   int to_l;\
76262306a36Sopenharmony_ci   \
76362306a36Sopenharmony_ci   to_l = (MAX_NR_KEY(Sh)+1 - lpar + vn->vn_nr_item + 1) / 2 -\
76462306a36Sopenharmony_ci	      (MAX_NR_KEY(Sh) + 1 - lpar);\
76562306a36Sopenharmony_ci	      \
76662306a36Sopenharmony_ci	      set_parameters (tb, h, to_l, 0, lnver, NULL, -1, -1);\
76762306a36Sopenharmony_ci}\
76862306a36Sopenharmony_cielse \
76962306a36Sopenharmony_ci{\
77062306a36Sopenharmony_ci   if (lset==LEFT_SHIFT_FLOW)\
77162306a36Sopenharmony_ci     set_parameters (tb, h, lpar, 0, lnver, snum012+lset,\
77262306a36Sopenharmony_ci		     tb->lbytes, -1);\
77362306a36Sopenharmony_ci   else\
77462306a36Sopenharmony_ci     set_parameters (tb, h, lpar - (tb->lbytes!=-1), 0, lnver, snum012+lset,\
77562306a36Sopenharmony_ci		     -1, -1);\
77662306a36Sopenharmony_ci}
77762306a36Sopenharmony_ci
77862306a36Sopenharmony_ci#define SET_PAR_SHIFT_RIGHT \
77962306a36Sopenharmony_ciif (h)\
78062306a36Sopenharmony_ci{\
78162306a36Sopenharmony_ci   int to_r;\
78262306a36Sopenharmony_ci   \
78362306a36Sopenharmony_ci   to_r = (MAX_NR_KEY(Sh)+1 - rpar + vn->vn_nr_item + 1) / 2 - (MAX_NR_KEY(Sh) + 1 - rpar);\
78462306a36Sopenharmony_ci   \
78562306a36Sopenharmony_ci   set_parameters (tb, h, 0, to_r, rnver, NULL, -1, -1);\
78662306a36Sopenharmony_ci}\
78762306a36Sopenharmony_cielse \
78862306a36Sopenharmony_ci{\
78962306a36Sopenharmony_ci   if (rset==RIGHT_SHIFT_FLOW)\
79062306a36Sopenharmony_ci     set_parameters (tb, h, 0, rpar, rnver, snum012+rset,\
79162306a36Sopenharmony_ci		  -1, tb->rbytes);\
79262306a36Sopenharmony_ci   else\
79362306a36Sopenharmony_ci     set_parameters (tb, h, 0, rpar - (tb->rbytes!=-1), rnver, snum012+rset,\
79462306a36Sopenharmony_ci		  -1, -1);\
79562306a36Sopenharmony_ci}
79662306a36Sopenharmony_ci
79762306a36Sopenharmony_cistatic void free_buffers_in_tb(struct tree_balance *tb)
79862306a36Sopenharmony_ci{
79962306a36Sopenharmony_ci	int i;
80062306a36Sopenharmony_ci
80162306a36Sopenharmony_ci	pathrelse(tb->tb_path);
80262306a36Sopenharmony_ci
80362306a36Sopenharmony_ci	for (i = 0; i < MAX_HEIGHT; i++) {
80462306a36Sopenharmony_ci		brelse(tb->L[i]);
80562306a36Sopenharmony_ci		brelse(tb->R[i]);
80662306a36Sopenharmony_ci		brelse(tb->FL[i]);
80762306a36Sopenharmony_ci		brelse(tb->FR[i]);
80862306a36Sopenharmony_ci		brelse(tb->CFL[i]);
80962306a36Sopenharmony_ci		brelse(tb->CFR[i]);
81062306a36Sopenharmony_ci
81162306a36Sopenharmony_ci		tb->L[i] = NULL;
81262306a36Sopenharmony_ci		tb->R[i] = NULL;
81362306a36Sopenharmony_ci		tb->FL[i] = NULL;
81462306a36Sopenharmony_ci		tb->FR[i] = NULL;
81562306a36Sopenharmony_ci		tb->CFL[i] = NULL;
81662306a36Sopenharmony_ci		tb->CFR[i] = NULL;
81762306a36Sopenharmony_ci	}
81862306a36Sopenharmony_ci}
81962306a36Sopenharmony_ci
82062306a36Sopenharmony_ci/*
82162306a36Sopenharmony_ci * Get new buffers for storing new nodes that are created while balancing.
82262306a36Sopenharmony_ci * Returns:	SCHEDULE_OCCURRED - schedule occurred while the function worked;
82362306a36Sopenharmony_ci *	        CARRY_ON - schedule didn't occur while the function worked;
82462306a36Sopenharmony_ci *	        NO_DISK_SPACE - no disk space.
82562306a36Sopenharmony_ci */
82662306a36Sopenharmony_ci/* The function is NOT SCHEDULE-SAFE! */
82762306a36Sopenharmony_cistatic int get_empty_nodes(struct tree_balance *tb, int h)
82862306a36Sopenharmony_ci{
82962306a36Sopenharmony_ci	struct buffer_head *new_bh, *Sh = PATH_H_PBUFFER(tb->tb_path, h);
83062306a36Sopenharmony_ci	b_blocknr_t *blocknr, blocknrs[MAX_AMOUNT_NEEDED] = { 0, };
83162306a36Sopenharmony_ci	int counter, number_of_freeblk;
83262306a36Sopenharmony_ci	int  amount_needed;	/* number of needed empty blocks */
83362306a36Sopenharmony_ci	int  retval = CARRY_ON;
83462306a36Sopenharmony_ci	struct super_block *sb = tb->tb_sb;
83562306a36Sopenharmony_ci
83662306a36Sopenharmony_ci	/*
83762306a36Sopenharmony_ci	 * number_of_freeblk is the number of empty blocks which have been
83862306a36Sopenharmony_ci	 * acquired for use by the balancing algorithm minus the number of
83962306a36Sopenharmony_ci	 * empty blocks used in the previous levels of the analysis,
84062306a36Sopenharmony_ci	 * number_of_freeblk = tb->cur_blknum can be non-zero if a schedule
84162306a36Sopenharmony_ci	 * occurs after empty blocks are acquired, and the balancing analysis
84262306a36Sopenharmony_ci	 * is then restarted, amount_needed is the number needed by this
84362306a36Sopenharmony_ci	 * level (h) of the balancing analysis.
84462306a36Sopenharmony_ci	 *
84562306a36Sopenharmony_ci	 * Note that for systems with many processes writing, it would be
84662306a36Sopenharmony_ci	 * more layout optimal to calculate the total number needed by all
84762306a36Sopenharmony_ci	 * levels and then to run reiserfs_new_blocks to get all of them at
84862306a36Sopenharmony_ci	 * once.
84962306a36Sopenharmony_ci	 */
85062306a36Sopenharmony_ci
85162306a36Sopenharmony_ci	/*
85262306a36Sopenharmony_ci	 * Initiate number_of_freeblk to the amount acquired prior to the
85362306a36Sopenharmony_ci	 * restart of the analysis or 0 if not restarted, then subtract the
85462306a36Sopenharmony_ci	 * amount needed by all of the levels of the tree below h.
85562306a36Sopenharmony_ci	 */
85662306a36Sopenharmony_ci	/* blknum includes S[h], so we subtract 1 in this calculation */
85762306a36Sopenharmony_ci	for (counter = 0, number_of_freeblk = tb->cur_blknum;
85862306a36Sopenharmony_ci	     counter < h; counter++)
85962306a36Sopenharmony_ci		number_of_freeblk -=
86062306a36Sopenharmony_ci		    (tb->blknum[counter]) ? (tb->blknum[counter] -
86162306a36Sopenharmony_ci						   1) : 0;
86262306a36Sopenharmony_ci
86362306a36Sopenharmony_ci	/* Allocate missing empty blocks. */
86462306a36Sopenharmony_ci	/* if Sh == 0  then we are getting a new root */
86562306a36Sopenharmony_ci	amount_needed = (Sh) ? (tb->blknum[h] - 1) : 1;
86662306a36Sopenharmony_ci	/*
86762306a36Sopenharmony_ci	 * Amount_needed = the amount that we need more than the
86862306a36Sopenharmony_ci	 * amount that we have.
86962306a36Sopenharmony_ci	 */
87062306a36Sopenharmony_ci	if (amount_needed > number_of_freeblk)
87162306a36Sopenharmony_ci		amount_needed -= number_of_freeblk;
87262306a36Sopenharmony_ci	else	/* If we have enough already then there is nothing to do. */
87362306a36Sopenharmony_ci		return CARRY_ON;
87462306a36Sopenharmony_ci
87562306a36Sopenharmony_ci	/*
87662306a36Sopenharmony_ci	 * No need to check quota - is not allocated for blocks used
87762306a36Sopenharmony_ci	 * for formatted nodes
87862306a36Sopenharmony_ci	 */
87962306a36Sopenharmony_ci	if (reiserfs_new_form_blocknrs(tb, blocknrs,
88062306a36Sopenharmony_ci				       amount_needed) == NO_DISK_SPACE)
88162306a36Sopenharmony_ci		return NO_DISK_SPACE;
88262306a36Sopenharmony_ci
88362306a36Sopenharmony_ci	/* for each blocknumber we just got, get a buffer and stick it on FEB */
88462306a36Sopenharmony_ci	for (blocknr = blocknrs, counter = 0;
88562306a36Sopenharmony_ci	     counter < amount_needed; blocknr++, counter++) {
88662306a36Sopenharmony_ci
88762306a36Sopenharmony_ci		RFALSE(!*blocknr,
88862306a36Sopenharmony_ci		       "PAP-8135: reiserfs_new_blocknrs failed when got new blocks");
88962306a36Sopenharmony_ci
89062306a36Sopenharmony_ci		new_bh = sb_getblk(sb, *blocknr);
89162306a36Sopenharmony_ci		RFALSE(buffer_dirty(new_bh) ||
89262306a36Sopenharmony_ci		       buffer_journaled(new_bh) ||
89362306a36Sopenharmony_ci		       buffer_journal_dirty(new_bh),
89462306a36Sopenharmony_ci		       "PAP-8140: journaled or dirty buffer %b for the new block",
89562306a36Sopenharmony_ci		       new_bh);
89662306a36Sopenharmony_ci
89762306a36Sopenharmony_ci		/* Put empty buffers into the array. */
89862306a36Sopenharmony_ci		RFALSE(tb->FEB[tb->cur_blknum],
89962306a36Sopenharmony_ci		       "PAP-8141: busy slot for new buffer");
90062306a36Sopenharmony_ci
90162306a36Sopenharmony_ci		set_buffer_journal_new(new_bh);
90262306a36Sopenharmony_ci		tb->FEB[tb->cur_blknum++] = new_bh;
90362306a36Sopenharmony_ci	}
90462306a36Sopenharmony_ci
90562306a36Sopenharmony_ci	if (retval == CARRY_ON && FILESYSTEM_CHANGED_TB(tb))
90662306a36Sopenharmony_ci		retval = REPEAT_SEARCH;
90762306a36Sopenharmony_ci
90862306a36Sopenharmony_ci	return retval;
90962306a36Sopenharmony_ci}
91062306a36Sopenharmony_ci
91162306a36Sopenharmony_ci/*
91262306a36Sopenharmony_ci * Get free space of the left neighbor, which is stored in the parent
91362306a36Sopenharmony_ci * node of the left neighbor.
91462306a36Sopenharmony_ci */
91562306a36Sopenharmony_cistatic int get_lfree(struct tree_balance *tb, int h)
91662306a36Sopenharmony_ci{
91762306a36Sopenharmony_ci	struct buffer_head *l, *f;
91862306a36Sopenharmony_ci	int order;
91962306a36Sopenharmony_ci
92062306a36Sopenharmony_ci	if ((f = PATH_H_PPARENT(tb->tb_path, h)) == NULL ||
92162306a36Sopenharmony_ci	    (l = tb->FL[h]) == NULL)
92262306a36Sopenharmony_ci		return 0;
92362306a36Sopenharmony_ci
92462306a36Sopenharmony_ci	if (f == l)
92562306a36Sopenharmony_ci		order = PATH_H_B_ITEM_ORDER(tb->tb_path, h) - 1;
92662306a36Sopenharmony_ci	else {
92762306a36Sopenharmony_ci		order = B_NR_ITEMS(l);
92862306a36Sopenharmony_ci		f = l;
92962306a36Sopenharmony_ci	}
93062306a36Sopenharmony_ci
93162306a36Sopenharmony_ci	return (MAX_CHILD_SIZE(f) - dc_size(B_N_CHILD(f, order)));
93262306a36Sopenharmony_ci}
93362306a36Sopenharmony_ci
93462306a36Sopenharmony_ci/*
93562306a36Sopenharmony_ci * Get free space of the right neighbor,
93662306a36Sopenharmony_ci * which is stored in the parent node of the right neighbor.
93762306a36Sopenharmony_ci */
93862306a36Sopenharmony_cistatic int get_rfree(struct tree_balance *tb, int h)
93962306a36Sopenharmony_ci{
94062306a36Sopenharmony_ci	struct buffer_head *r, *f;
94162306a36Sopenharmony_ci	int order;
94262306a36Sopenharmony_ci
94362306a36Sopenharmony_ci	if ((f = PATH_H_PPARENT(tb->tb_path, h)) == NULL ||
94462306a36Sopenharmony_ci	    (r = tb->FR[h]) == NULL)
94562306a36Sopenharmony_ci		return 0;
94662306a36Sopenharmony_ci
94762306a36Sopenharmony_ci	if (f == r)
94862306a36Sopenharmony_ci		order = PATH_H_B_ITEM_ORDER(tb->tb_path, h) + 1;
94962306a36Sopenharmony_ci	else {
95062306a36Sopenharmony_ci		order = 0;
95162306a36Sopenharmony_ci		f = r;
95262306a36Sopenharmony_ci	}
95362306a36Sopenharmony_ci
95462306a36Sopenharmony_ci	return (MAX_CHILD_SIZE(f) - dc_size(B_N_CHILD(f, order)));
95562306a36Sopenharmony_ci
95662306a36Sopenharmony_ci}
95762306a36Sopenharmony_ci
95862306a36Sopenharmony_ci/* Check whether left neighbor is in memory. */
95962306a36Sopenharmony_cistatic int is_left_neighbor_in_cache(struct tree_balance *tb, int h)
96062306a36Sopenharmony_ci{
96162306a36Sopenharmony_ci	struct buffer_head *father, *left;
96262306a36Sopenharmony_ci	struct super_block *sb = tb->tb_sb;
96362306a36Sopenharmony_ci	b_blocknr_t left_neighbor_blocknr;
96462306a36Sopenharmony_ci	int left_neighbor_position;
96562306a36Sopenharmony_ci
96662306a36Sopenharmony_ci	/* Father of the left neighbor does not exist. */
96762306a36Sopenharmony_ci	if (!tb->FL[h])
96862306a36Sopenharmony_ci		return 0;
96962306a36Sopenharmony_ci
97062306a36Sopenharmony_ci	/* Calculate father of the node to be balanced. */
97162306a36Sopenharmony_ci	father = PATH_H_PBUFFER(tb->tb_path, h + 1);
97262306a36Sopenharmony_ci
97362306a36Sopenharmony_ci	RFALSE(!father ||
97462306a36Sopenharmony_ci	       !B_IS_IN_TREE(father) ||
97562306a36Sopenharmony_ci	       !B_IS_IN_TREE(tb->FL[h]) ||
97662306a36Sopenharmony_ci	       !buffer_uptodate(father) ||
97762306a36Sopenharmony_ci	       !buffer_uptodate(tb->FL[h]),
97862306a36Sopenharmony_ci	       "vs-8165: F[h] (%b) or FL[h] (%b) is invalid",
97962306a36Sopenharmony_ci	       father, tb->FL[h]);
98062306a36Sopenharmony_ci
98162306a36Sopenharmony_ci	/*
98262306a36Sopenharmony_ci	 * Get position of the pointer to the left neighbor
98362306a36Sopenharmony_ci	 * into the left father.
98462306a36Sopenharmony_ci	 */
98562306a36Sopenharmony_ci	left_neighbor_position = (father == tb->FL[h]) ?
98662306a36Sopenharmony_ci	    tb->lkey[h] : B_NR_ITEMS(tb->FL[h]);
98762306a36Sopenharmony_ci	/* Get left neighbor block number. */
98862306a36Sopenharmony_ci	left_neighbor_blocknr =
98962306a36Sopenharmony_ci	    B_N_CHILD_NUM(tb->FL[h], left_neighbor_position);
99062306a36Sopenharmony_ci	/* Look for the left neighbor in the cache. */
99162306a36Sopenharmony_ci	if ((left = sb_find_get_block(sb, left_neighbor_blocknr))) {
99262306a36Sopenharmony_ci
99362306a36Sopenharmony_ci		RFALSE(buffer_uptodate(left) && !B_IS_IN_TREE(left),
99462306a36Sopenharmony_ci		       "vs-8170: left neighbor (%b %z) is not in the tree",
99562306a36Sopenharmony_ci		       left, left);
99662306a36Sopenharmony_ci		put_bh(left);
99762306a36Sopenharmony_ci		return 1;
99862306a36Sopenharmony_ci	}
99962306a36Sopenharmony_ci
100062306a36Sopenharmony_ci	return 0;
100162306a36Sopenharmony_ci}
100262306a36Sopenharmony_ci
100362306a36Sopenharmony_ci#define LEFT_PARENTS  'l'
100462306a36Sopenharmony_ci#define RIGHT_PARENTS 'r'
100562306a36Sopenharmony_ci
100662306a36Sopenharmony_cistatic void decrement_key(struct cpu_key *key)
100762306a36Sopenharmony_ci{
100862306a36Sopenharmony_ci	/* call item specific function for this key */
100962306a36Sopenharmony_ci	item_ops[cpu_key_k_type(key)]->decrement_key(key);
101062306a36Sopenharmony_ci}
101162306a36Sopenharmony_ci
101262306a36Sopenharmony_ci/*
101362306a36Sopenharmony_ci * Calculate far left/right parent of the left/right neighbor of the
101462306a36Sopenharmony_ci * current node, that is calculate the left/right (FL[h]/FR[h]) neighbor
101562306a36Sopenharmony_ci * of the parent F[h].
101662306a36Sopenharmony_ci * Calculate left/right common parent of the current node and L[h]/R[h].
101762306a36Sopenharmony_ci * Calculate left/right delimiting key position.
101862306a36Sopenharmony_ci * Returns:	PATH_INCORRECT    - path in the tree is not correct
101962306a36Sopenharmony_ci *		SCHEDULE_OCCURRED - schedule occurred while the function worked
102062306a36Sopenharmony_ci *	        CARRY_ON          - schedule didn't occur while the function
102162306a36Sopenharmony_ci *				    worked
102262306a36Sopenharmony_ci */
102362306a36Sopenharmony_cistatic int get_far_parent(struct tree_balance *tb,
102462306a36Sopenharmony_ci			  int h,
102562306a36Sopenharmony_ci			  struct buffer_head **pfather,
102662306a36Sopenharmony_ci			  struct buffer_head **pcom_father, char c_lr_par)
102762306a36Sopenharmony_ci{
102862306a36Sopenharmony_ci	struct buffer_head *parent;
102962306a36Sopenharmony_ci	INITIALIZE_PATH(s_path_to_neighbor_father);
103062306a36Sopenharmony_ci	struct treepath *path = tb->tb_path;
103162306a36Sopenharmony_ci	struct cpu_key s_lr_father_key;
103262306a36Sopenharmony_ci	int counter,
103362306a36Sopenharmony_ci	    position = INT_MAX,
103462306a36Sopenharmony_ci	    first_last_position = 0,
103562306a36Sopenharmony_ci	    path_offset = PATH_H_PATH_OFFSET(path, h);
103662306a36Sopenharmony_ci
103762306a36Sopenharmony_ci	/*
103862306a36Sopenharmony_ci	 * Starting from F[h] go upwards in the tree, and look for the common
103962306a36Sopenharmony_ci	 * ancestor of F[h], and its neighbor l/r, that should be obtained.
104062306a36Sopenharmony_ci	 */
104162306a36Sopenharmony_ci
104262306a36Sopenharmony_ci	counter = path_offset;
104362306a36Sopenharmony_ci
104462306a36Sopenharmony_ci	RFALSE(counter < FIRST_PATH_ELEMENT_OFFSET,
104562306a36Sopenharmony_ci	       "PAP-8180: invalid path length");
104662306a36Sopenharmony_ci
104762306a36Sopenharmony_ci	for (; counter > FIRST_PATH_ELEMENT_OFFSET; counter--) {
104862306a36Sopenharmony_ci		/*
104962306a36Sopenharmony_ci		 * Check whether parent of the current buffer in the path
105062306a36Sopenharmony_ci		 * is really parent in the tree.
105162306a36Sopenharmony_ci		 */
105262306a36Sopenharmony_ci		if (!B_IS_IN_TREE
105362306a36Sopenharmony_ci		    (parent = PATH_OFFSET_PBUFFER(path, counter - 1)))
105462306a36Sopenharmony_ci			return REPEAT_SEARCH;
105562306a36Sopenharmony_ci
105662306a36Sopenharmony_ci		/* Check whether position in the parent is correct. */
105762306a36Sopenharmony_ci		if ((position =
105862306a36Sopenharmony_ci		     PATH_OFFSET_POSITION(path,
105962306a36Sopenharmony_ci					  counter - 1)) >
106062306a36Sopenharmony_ci		    B_NR_ITEMS(parent))
106162306a36Sopenharmony_ci			return REPEAT_SEARCH;
106262306a36Sopenharmony_ci
106362306a36Sopenharmony_ci		/*
106462306a36Sopenharmony_ci		 * Check whether parent at the path really points
106562306a36Sopenharmony_ci		 * to the child.
106662306a36Sopenharmony_ci		 */
106762306a36Sopenharmony_ci		if (B_N_CHILD_NUM(parent, position) !=
106862306a36Sopenharmony_ci		    PATH_OFFSET_PBUFFER(path, counter)->b_blocknr)
106962306a36Sopenharmony_ci			return REPEAT_SEARCH;
107062306a36Sopenharmony_ci
107162306a36Sopenharmony_ci		/*
107262306a36Sopenharmony_ci		 * Return delimiting key if position in the parent is not
107362306a36Sopenharmony_ci		 * equal to first/last one.
107462306a36Sopenharmony_ci		 */
107562306a36Sopenharmony_ci		if (c_lr_par == RIGHT_PARENTS)
107662306a36Sopenharmony_ci			first_last_position = B_NR_ITEMS(parent);
107762306a36Sopenharmony_ci		if (position != first_last_position) {
107862306a36Sopenharmony_ci			*pcom_father = parent;
107962306a36Sopenharmony_ci			get_bh(*pcom_father);
108062306a36Sopenharmony_ci			/*(*pcom_father = parent)->b_count++; */
108162306a36Sopenharmony_ci			break;
108262306a36Sopenharmony_ci		}
108362306a36Sopenharmony_ci	}
108462306a36Sopenharmony_ci
108562306a36Sopenharmony_ci	/* if we are in the root of the tree, then there is no common father */
108662306a36Sopenharmony_ci	if (counter == FIRST_PATH_ELEMENT_OFFSET) {
108762306a36Sopenharmony_ci		/*
108862306a36Sopenharmony_ci		 * Check whether first buffer in the path is the
108962306a36Sopenharmony_ci		 * root of the tree.
109062306a36Sopenharmony_ci		 */
109162306a36Sopenharmony_ci		if (PATH_OFFSET_PBUFFER
109262306a36Sopenharmony_ci		    (tb->tb_path,
109362306a36Sopenharmony_ci		     FIRST_PATH_ELEMENT_OFFSET)->b_blocknr ==
109462306a36Sopenharmony_ci		    SB_ROOT_BLOCK(tb->tb_sb)) {
109562306a36Sopenharmony_ci			*pfather = *pcom_father = NULL;
109662306a36Sopenharmony_ci			return CARRY_ON;
109762306a36Sopenharmony_ci		}
109862306a36Sopenharmony_ci		return REPEAT_SEARCH;
109962306a36Sopenharmony_ci	}
110062306a36Sopenharmony_ci
110162306a36Sopenharmony_ci	RFALSE(B_LEVEL(*pcom_father) <= DISK_LEAF_NODE_LEVEL,
110262306a36Sopenharmony_ci	       "PAP-8185: (%b %z) level too small",
110362306a36Sopenharmony_ci	       *pcom_father, *pcom_father);
110462306a36Sopenharmony_ci
110562306a36Sopenharmony_ci	/* Check whether the common parent is locked. */
110662306a36Sopenharmony_ci
110762306a36Sopenharmony_ci	if (buffer_locked(*pcom_father)) {
110862306a36Sopenharmony_ci
110962306a36Sopenharmony_ci		/* Release the write lock while the buffer is busy */
111062306a36Sopenharmony_ci		int depth = reiserfs_write_unlock_nested(tb->tb_sb);
111162306a36Sopenharmony_ci		__wait_on_buffer(*pcom_father);
111262306a36Sopenharmony_ci		reiserfs_write_lock_nested(tb->tb_sb, depth);
111362306a36Sopenharmony_ci		if (FILESYSTEM_CHANGED_TB(tb)) {
111462306a36Sopenharmony_ci			brelse(*pcom_father);
111562306a36Sopenharmony_ci			return REPEAT_SEARCH;
111662306a36Sopenharmony_ci		}
111762306a36Sopenharmony_ci	}
111862306a36Sopenharmony_ci
111962306a36Sopenharmony_ci	/*
112062306a36Sopenharmony_ci	 * So, we got common parent of the current node and its
112162306a36Sopenharmony_ci	 * left/right neighbor.  Now we are getting the parent of the
112262306a36Sopenharmony_ci	 * left/right neighbor.
112362306a36Sopenharmony_ci	 */
112462306a36Sopenharmony_ci
112562306a36Sopenharmony_ci	/* Form key to get parent of the left/right neighbor. */
112662306a36Sopenharmony_ci	le_key2cpu_key(&s_lr_father_key,
112762306a36Sopenharmony_ci		       internal_key(*pcom_father,
112862306a36Sopenharmony_ci				      (c_lr_par ==
112962306a36Sopenharmony_ci				       LEFT_PARENTS) ? (tb->lkey[h - 1] =
113062306a36Sopenharmony_ci							position -
113162306a36Sopenharmony_ci							1) : (tb->rkey[h -
113262306a36Sopenharmony_ci									   1] =
113362306a36Sopenharmony_ci							      position)));
113462306a36Sopenharmony_ci
113562306a36Sopenharmony_ci	if (c_lr_par == LEFT_PARENTS)
113662306a36Sopenharmony_ci		decrement_key(&s_lr_father_key);
113762306a36Sopenharmony_ci
113862306a36Sopenharmony_ci	if (search_by_key
113962306a36Sopenharmony_ci	    (tb->tb_sb, &s_lr_father_key, &s_path_to_neighbor_father,
114062306a36Sopenharmony_ci	     h + 1) == IO_ERROR)
114162306a36Sopenharmony_ci		/* path is released */
114262306a36Sopenharmony_ci		return IO_ERROR;
114362306a36Sopenharmony_ci
114462306a36Sopenharmony_ci	if (FILESYSTEM_CHANGED_TB(tb)) {
114562306a36Sopenharmony_ci		pathrelse(&s_path_to_neighbor_father);
114662306a36Sopenharmony_ci		brelse(*pcom_father);
114762306a36Sopenharmony_ci		return REPEAT_SEARCH;
114862306a36Sopenharmony_ci	}
114962306a36Sopenharmony_ci
115062306a36Sopenharmony_ci	*pfather = PATH_PLAST_BUFFER(&s_path_to_neighbor_father);
115162306a36Sopenharmony_ci
115262306a36Sopenharmony_ci	RFALSE(B_LEVEL(*pfather) != h + 1,
115362306a36Sopenharmony_ci	       "PAP-8190: (%b %z) level too small", *pfather, *pfather);
115462306a36Sopenharmony_ci	RFALSE(s_path_to_neighbor_father.path_length <
115562306a36Sopenharmony_ci	       FIRST_PATH_ELEMENT_OFFSET, "PAP-8192: path length is too small");
115662306a36Sopenharmony_ci
115762306a36Sopenharmony_ci	s_path_to_neighbor_father.path_length--;
115862306a36Sopenharmony_ci	pathrelse(&s_path_to_neighbor_father);
115962306a36Sopenharmony_ci	return CARRY_ON;
116062306a36Sopenharmony_ci}
116162306a36Sopenharmony_ci
116262306a36Sopenharmony_ci/*
116362306a36Sopenharmony_ci * Get parents of neighbors of node in the path(S[path_offset]) and
116462306a36Sopenharmony_ci * common parents of S[path_offset] and L[path_offset]/R[path_offset]:
116562306a36Sopenharmony_ci * F[path_offset], FL[path_offset], FR[path_offset], CFL[path_offset],
116662306a36Sopenharmony_ci * CFR[path_offset].
116762306a36Sopenharmony_ci * Calculate numbers of left and right delimiting keys position:
116862306a36Sopenharmony_ci * lkey[path_offset], rkey[path_offset].
116962306a36Sopenharmony_ci * Returns:	SCHEDULE_OCCURRED - schedule occurred while the function worked
117062306a36Sopenharmony_ci *	        CARRY_ON - schedule didn't occur while the function worked
117162306a36Sopenharmony_ci */
117262306a36Sopenharmony_cistatic int get_parents(struct tree_balance *tb, int h)
117362306a36Sopenharmony_ci{
117462306a36Sopenharmony_ci	struct treepath *path = tb->tb_path;
117562306a36Sopenharmony_ci	int position,
117662306a36Sopenharmony_ci	    ret,
117762306a36Sopenharmony_ci	    path_offset = PATH_H_PATH_OFFSET(tb->tb_path, h);
117862306a36Sopenharmony_ci	struct buffer_head *curf, *curcf;
117962306a36Sopenharmony_ci
118062306a36Sopenharmony_ci	/* Current node is the root of the tree or will be root of the tree */
118162306a36Sopenharmony_ci	if (path_offset <= FIRST_PATH_ELEMENT_OFFSET) {
118262306a36Sopenharmony_ci		/*
118362306a36Sopenharmony_ci		 * The root can not have parents.
118462306a36Sopenharmony_ci		 * Release nodes which previously were obtained as
118562306a36Sopenharmony_ci		 * parents of the current node neighbors.
118662306a36Sopenharmony_ci		 */
118762306a36Sopenharmony_ci		brelse(tb->FL[h]);
118862306a36Sopenharmony_ci		brelse(tb->CFL[h]);
118962306a36Sopenharmony_ci		brelse(tb->FR[h]);
119062306a36Sopenharmony_ci		brelse(tb->CFR[h]);
119162306a36Sopenharmony_ci		tb->FL[h]  = NULL;
119262306a36Sopenharmony_ci		tb->CFL[h] = NULL;
119362306a36Sopenharmony_ci		tb->FR[h]  = NULL;
119462306a36Sopenharmony_ci		tb->CFR[h] = NULL;
119562306a36Sopenharmony_ci		return CARRY_ON;
119662306a36Sopenharmony_ci	}
119762306a36Sopenharmony_ci
119862306a36Sopenharmony_ci	/* Get parent FL[path_offset] of L[path_offset]. */
119962306a36Sopenharmony_ci	position = PATH_OFFSET_POSITION(path, path_offset - 1);
120062306a36Sopenharmony_ci	if (position) {
120162306a36Sopenharmony_ci		/* Current node is not the first child of its parent. */
120262306a36Sopenharmony_ci		curf = PATH_OFFSET_PBUFFER(path, path_offset - 1);
120362306a36Sopenharmony_ci		curcf = PATH_OFFSET_PBUFFER(path, path_offset - 1);
120462306a36Sopenharmony_ci		get_bh(curf);
120562306a36Sopenharmony_ci		get_bh(curf);
120662306a36Sopenharmony_ci		tb->lkey[h] = position - 1;
120762306a36Sopenharmony_ci	} else {
120862306a36Sopenharmony_ci		/*
120962306a36Sopenharmony_ci		 * Calculate current parent of L[path_offset], which is the
121062306a36Sopenharmony_ci		 * left neighbor of the current node.  Calculate current
121162306a36Sopenharmony_ci		 * common parent of L[path_offset] and the current node.
121262306a36Sopenharmony_ci		 * Note that CFL[path_offset] not equal FL[path_offset] and
121362306a36Sopenharmony_ci		 * CFL[path_offset] not equal F[path_offset].
121462306a36Sopenharmony_ci		 * Calculate lkey[path_offset].
121562306a36Sopenharmony_ci		 */
121662306a36Sopenharmony_ci		if ((ret = get_far_parent(tb, h + 1, &curf,
121762306a36Sopenharmony_ci						  &curcf,
121862306a36Sopenharmony_ci						  LEFT_PARENTS)) != CARRY_ON)
121962306a36Sopenharmony_ci			return ret;
122062306a36Sopenharmony_ci	}
122162306a36Sopenharmony_ci
122262306a36Sopenharmony_ci	brelse(tb->FL[h]);
122362306a36Sopenharmony_ci	tb->FL[h] = curf;	/* New initialization of FL[h]. */
122462306a36Sopenharmony_ci	brelse(tb->CFL[h]);
122562306a36Sopenharmony_ci	tb->CFL[h] = curcf;	/* New initialization of CFL[h]. */
122662306a36Sopenharmony_ci
122762306a36Sopenharmony_ci	RFALSE((curf && !B_IS_IN_TREE(curf)) ||
122862306a36Sopenharmony_ci	       (curcf && !B_IS_IN_TREE(curcf)),
122962306a36Sopenharmony_ci	       "PAP-8195: FL (%b) or CFL (%b) is invalid", curf, curcf);
123062306a36Sopenharmony_ci
123162306a36Sopenharmony_ci	/* Get parent FR[h] of R[h]. */
123262306a36Sopenharmony_ci
123362306a36Sopenharmony_ci	/* Current node is the last child of F[h]. FR[h] != F[h]. */
123462306a36Sopenharmony_ci	if (position == B_NR_ITEMS(PATH_H_PBUFFER(path, h + 1))) {
123562306a36Sopenharmony_ci		/*
123662306a36Sopenharmony_ci		 * Calculate current parent of R[h], which is the right
123762306a36Sopenharmony_ci		 * neighbor of F[h].  Calculate current common parent of
123862306a36Sopenharmony_ci		 * R[h] and current node. Note that CFR[h] not equal
123962306a36Sopenharmony_ci		 * FR[path_offset] and CFR[h] not equal F[h].
124062306a36Sopenharmony_ci		 */
124162306a36Sopenharmony_ci		if ((ret =
124262306a36Sopenharmony_ci		     get_far_parent(tb, h + 1, &curf, &curcf,
124362306a36Sopenharmony_ci				    RIGHT_PARENTS)) != CARRY_ON)
124462306a36Sopenharmony_ci			return ret;
124562306a36Sopenharmony_ci	} else {
124662306a36Sopenharmony_ci		/* Current node is not the last child of its parent F[h]. */
124762306a36Sopenharmony_ci		curf = PATH_OFFSET_PBUFFER(path, path_offset - 1);
124862306a36Sopenharmony_ci		curcf = PATH_OFFSET_PBUFFER(path, path_offset - 1);
124962306a36Sopenharmony_ci		get_bh(curf);
125062306a36Sopenharmony_ci		get_bh(curf);
125162306a36Sopenharmony_ci		tb->rkey[h] = position;
125262306a36Sopenharmony_ci	}
125362306a36Sopenharmony_ci
125462306a36Sopenharmony_ci	brelse(tb->FR[h]);
125562306a36Sopenharmony_ci	/* New initialization of FR[path_offset]. */
125662306a36Sopenharmony_ci	tb->FR[h] = curf;
125762306a36Sopenharmony_ci
125862306a36Sopenharmony_ci	brelse(tb->CFR[h]);
125962306a36Sopenharmony_ci	/* New initialization of CFR[path_offset]. */
126062306a36Sopenharmony_ci	tb->CFR[h] = curcf;
126162306a36Sopenharmony_ci
126262306a36Sopenharmony_ci	RFALSE((curf && !B_IS_IN_TREE(curf)) ||
126362306a36Sopenharmony_ci	       (curcf && !B_IS_IN_TREE(curcf)),
126462306a36Sopenharmony_ci	       "PAP-8205: FR (%b) or CFR (%b) is invalid", curf, curcf);
126562306a36Sopenharmony_ci
126662306a36Sopenharmony_ci	return CARRY_ON;
126762306a36Sopenharmony_ci}
126862306a36Sopenharmony_ci
126962306a36Sopenharmony_ci/*
127062306a36Sopenharmony_ci * it is possible to remove node as result of shiftings to
127162306a36Sopenharmony_ci * neighbors even when we insert or paste item.
127262306a36Sopenharmony_ci */
127362306a36Sopenharmony_cistatic inline int can_node_be_removed(int mode, int lfree, int sfree, int rfree,
127462306a36Sopenharmony_ci				      struct tree_balance *tb, int h)
127562306a36Sopenharmony_ci{
127662306a36Sopenharmony_ci	struct buffer_head *Sh = PATH_H_PBUFFER(tb->tb_path, h);
127762306a36Sopenharmony_ci	int levbytes = tb->insert_size[h];
127862306a36Sopenharmony_ci	struct item_head *ih;
127962306a36Sopenharmony_ci	struct reiserfs_key *r_key = NULL;
128062306a36Sopenharmony_ci
128162306a36Sopenharmony_ci	ih = item_head(Sh, 0);
128262306a36Sopenharmony_ci	if (tb->CFR[h])
128362306a36Sopenharmony_ci		r_key = internal_key(tb->CFR[h], tb->rkey[h]);
128462306a36Sopenharmony_ci
128562306a36Sopenharmony_ci	if (lfree + rfree + sfree < MAX_CHILD_SIZE(Sh) + levbytes
128662306a36Sopenharmony_ci	    /* shifting may merge items which might save space */
128762306a36Sopenharmony_ci	    -
128862306a36Sopenharmony_ci	    ((!h
128962306a36Sopenharmony_ci	      && op_is_left_mergeable(&ih->ih_key, Sh->b_size)) ? IH_SIZE : 0)
129062306a36Sopenharmony_ci	    -
129162306a36Sopenharmony_ci	    ((!h && r_key
129262306a36Sopenharmony_ci	      && op_is_left_mergeable(r_key, Sh->b_size)) ? IH_SIZE : 0)
129362306a36Sopenharmony_ci	    + ((h) ? KEY_SIZE : 0)) {
129462306a36Sopenharmony_ci		/* node can not be removed */
129562306a36Sopenharmony_ci		if (sfree >= levbytes) {
129662306a36Sopenharmony_ci			/* new item fits into node S[h] without any shifting */
129762306a36Sopenharmony_ci			if (!h)
129862306a36Sopenharmony_ci				tb->s0num =
129962306a36Sopenharmony_ci				    B_NR_ITEMS(Sh) +
130062306a36Sopenharmony_ci				    ((mode == M_INSERT) ? 1 : 0);
130162306a36Sopenharmony_ci			set_parameters(tb, h, 0, 0, 1, NULL, -1, -1);
130262306a36Sopenharmony_ci			return NO_BALANCING_NEEDED;
130362306a36Sopenharmony_ci		}
130462306a36Sopenharmony_ci	}
130562306a36Sopenharmony_ci	PROC_INFO_INC(tb->tb_sb, can_node_be_removed[h]);
130662306a36Sopenharmony_ci	return !NO_BALANCING_NEEDED;
130762306a36Sopenharmony_ci}
130862306a36Sopenharmony_ci
130962306a36Sopenharmony_ci/*
131062306a36Sopenharmony_ci * Check whether current node S[h] is balanced when increasing its size by
131162306a36Sopenharmony_ci * Inserting or Pasting.
131262306a36Sopenharmony_ci * Calculate parameters for balancing for current level h.
131362306a36Sopenharmony_ci * Parameters:
131462306a36Sopenharmony_ci *	tb	tree_balance structure;
131562306a36Sopenharmony_ci *	h	current level of the node;
131662306a36Sopenharmony_ci *	inum	item number in S[h];
131762306a36Sopenharmony_ci *	mode	i - insert, p - paste;
131862306a36Sopenharmony_ci * Returns:	1 - schedule occurred;
131962306a36Sopenharmony_ci *	        0 - balancing for higher levels needed;
132062306a36Sopenharmony_ci *	       -1 - no balancing for higher levels needed;
132162306a36Sopenharmony_ci *	       -2 - no disk space.
132262306a36Sopenharmony_ci */
132362306a36Sopenharmony_ci/* ip means Inserting or Pasting */
132462306a36Sopenharmony_cistatic int ip_check_balance(struct tree_balance *tb, int h)
132562306a36Sopenharmony_ci{
132662306a36Sopenharmony_ci	struct virtual_node *vn = tb->tb_vn;
132762306a36Sopenharmony_ci	/*
132862306a36Sopenharmony_ci	 * Number of bytes that must be inserted into (value is negative
132962306a36Sopenharmony_ci	 * if bytes are deleted) buffer which contains node being balanced.
133062306a36Sopenharmony_ci	 * The mnemonic is that the attempted change in node space used
133162306a36Sopenharmony_ci	 * level is levbytes bytes.
133262306a36Sopenharmony_ci	 */
133362306a36Sopenharmony_ci	int levbytes;
133462306a36Sopenharmony_ci	int ret;
133562306a36Sopenharmony_ci
133662306a36Sopenharmony_ci	int lfree, sfree, rfree /* free space in L, S and R */ ;
133762306a36Sopenharmony_ci
133862306a36Sopenharmony_ci	/*
133962306a36Sopenharmony_ci	 * nver is short for number of vertixes, and lnver is the number if
134062306a36Sopenharmony_ci	 * we shift to the left, rnver is the number if we shift to the
134162306a36Sopenharmony_ci	 * right, and lrnver is the number if we shift in both directions.
134262306a36Sopenharmony_ci	 * The goal is to minimize first the number of vertixes, and second,
134362306a36Sopenharmony_ci	 * the number of vertixes whose contents are changed by shifting,
134462306a36Sopenharmony_ci	 * and third the number of uncached vertixes whose contents are
134562306a36Sopenharmony_ci	 * changed by shifting and must be read from disk.
134662306a36Sopenharmony_ci	 */
134762306a36Sopenharmony_ci	int nver, lnver, rnver, lrnver;
134862306a36Sopenharmony_ci
134962306a36Sopenharmony_ci	/*
135062306a36Sopenharmony_ci	 * used at leaf level only, S0 = S[0] is the node being balanced,
135162306a36Sopenharmony_ci	 * sInum [ I = 0,1,2 ] is the number of items that will
135262306a36Sopenharmony_ci	 * remain in node SI after balancing.  S1 and S2 are new
135362306a36Sopenharmony_ci	 * nodes that might be created.
135462306a36Sopenharmony_ci	 */
135562306a36Sopenharmony_ci
135662306a36Sopenharmony_ci	/*
135762306a36Sopenharmony_ci	 * we perform 8 calls to get_num_ver().  For each call we
135862306a36Sopenharmony_ci	 * calculate five parameters.  where 4th parameter is s1bytes
135962306a36Sopenharmony_ci	 * and 5th - s2bytes
136062306a36Sopenharmony_ci	 *
136162306a36Sopenharmony_ci	 * s0num, s1num, s2num for 8 cases
136262306a36Sopenharmony_ci	 * 0,1 - do not shift and do not shift but bottle
136362306a36Sopenharmony_ci	 * 2   - shift only whole item to left
136462306a36Sopenharmony_ci	 * 3   - shift to left and bottle as much as possible
136562306a36Sopenharmony_ci	 * 4,5 - shift to right (whole items and as much as possible
136662306a36Sopenharmony_ci	 * 6,7 - shift to both directions (whole items and as much as possible)
136762306a36Sopenharmony_ci	 */
136862306a36Sopenharmony_ci	short snum012[40] = { 0, };
136962306a36Sopenharmony_ci
137062306a36Sopenharmony_ci	/* Sh is the node whose balance is currently being checked */
137162306a36Sopenharmony_ci	struct buffer_head *Sh;
137262306a36Sopenharmony_ci
137362306a36Sopenharmony_ci	Sh = PATH_H_PBUFFER(tb->tb_path, h);
137462306a36Sopenharmony_ci	levbytes = tb->insert_size[h];
137562306a36Sopenharmony_ci
137662306a36Sopenharmony_ci	/* Calculate balance parameters for creating new root. */
137762306a36Sopenharmony_ci	if (!Sh) {
137862306a36Sopenharmony_ci		if (!h)
137962306a36Sopenharmony_ci			reiserfs_panic(tb->tb_sb, "vs-8210",
138062306a36Sopenharmony_ci				       "S[0] can not be 0");
138162306a36Sopenharmony_ci		switch (ret = get_empty_nodes(tb, h)) {
138262306a36Sopenharmony_ci		/* no balancing for higher levels needed */
138362306a36Sopenharmony_ci		case CARRY_ON:
138462306a36Sopenharmony_ci			set_parameters(tb, h, 0, 0, 1, NULL, -1, -1);
138562306a36Sopenharmony_ci			return NO_BALANCING_NEEDED;
138662306a36Sopenharmony_ci
138762306a36Sopenharmony_ci		case NO_DISK_SPACE:
138862306a36Sopenharmony_ci		case REPEAT_SEARCH:
138962306a36Sopenharmony_ci			return ret;
139062306a36Sopenharmony_ci		default:
139162306a36Sopenharmony_ci			reiserfs_panic(tb->tb_sb, "vs-8215", "incorrect "
139262306a36Sopenharmony_ci				       "return value of get_empty_nodes");
139362306a36Sopenharmony_ci		}
139462306a36Sopenharmony_ci	}
139562306a36Sopenharmony_ci
139662306a36Sopenharmony_ci	/* get parents of S[h] neighbors. */
139762306a36Sopenharmony_ci	ret = get_parents(tb, h);
139862306a36Sopenharmony_ci	if (ret != CARRY_ON)
139962306a36Sopenharmony_ci		return ret;
140062306a36Sopenharmony_ci
140162306a36Sopenharmony_ci	sfree = B_FREE_SPACE(Sh);
140262306a36Sopenharmony_ci
140362306a36Sopenharmony_ci	/* get free space of neighbors */
140462306a36Sopenharmony_ci	rfree = get_rfree(tb, h);
140562306a36Sopenharmony_ci	lfree = get_lfree(tb, h);
140662306a36Sopenharmony_ci
140762306a36Sopenharmony_ci	/* and new item fits into node S[h] without any shifting */
140862306a36Sopenharmony_ci	if (can_node_be_removed(vn->vn_mode, lfree, sfree, rfree, tb, h) ==
140962306a36Sopenharmony_ci	    NO_BALANCING_NEEDED)
141062306a36Sopenharmony_ci		return NO_BALANCING_NEEDED;
141162306a36Sopenharmony_ci
141262306a36Sopenharmony_ci	create_virtual_node(tb, h);
141362306a36Sopenharmony_ci
141462306a36Sopenharmony_ci	/*
141562306a36Sopenharmony_ci	 * determine maximal number of items we can shift to the left
141662306a36Sopenharmony_ci	 * neighbor (in tb structure) and the maximal number of bytes
141762306a36Sopenharmony_ci	 * that can flow to the left neighbor from the left most liquid
141862306a36Sopenharmony_ci	 * item that cannot be shifted from S[0] entirely (returned value)
141962306a36Sopenharmony_ci	 */
142062306a36Sopenharmony_ci	check_left(tb, h, lfree);
142162306a36Sopenharmony_ci
142262306a36Sopenharmony_ci	/*
142362306a36Sopenharmony_ci	 * determine maximal number of items we can shift to the right
142462306a36Sopenharmony_ci	 * neighbor (in tb structure) and the maximal number of bytes
142562306a36Sopenharmony_ci	 * that can flow to the right neighbor from the right most liquid
142662306a36Sopenharmony_ci	 * item that cannot be shifted from S[0] entirely (returned value)
142762306a36Sopenharmony_ci	 */
142862306a36Sopenharmony_ci	check_right(tb, h, rfree);
142962306a36Sopenharmony_ci
143062306a36Sopenharmony_ci	/*
143162306a36Sopenharmony_ci	 * all contents of internal node S[h] can be moved into its
143262306a36Sopenharmony_ci	 * neighbors, S[h] will be removed after balancing
143362306a36Sopenharmony_ci	 */
143462306a36Sopenharmony_ci	if (h && (tb->rnum[h] + tb->lnum[h] >= vn->vn_nr_item + 1)) {
143562306a36Sopenharmony_ci		int to_r;
143662306a36Sopenharmony_ci
143762306a36Sopenharmony_ci		/*
143862306a36Sopenharmony_ci		 * Since we are working on internal nodes, and our internal
143962306a36Sopenharmony_ci		 * nodes have fixed size entries, then we can balance by the
144062306a36Sopenharmony_ci		 * number of items rather than the space they consume.  In this
144162306a36Sopenharmony_ci		 * routine we set the left node equal to the right node,
144262306a36Sopenharmony_ci		 * allowing a difference of less than or equal to 1 child
144362306a36Sopenharmony_ci		 * pointer.
144462306a36Sopenharmony_ci		 */
144562306a36Sopenharmony_ci		to_r =
144662306a36Sopenharmony_ci		    ((MAX_NR_KEY(Sh) << 1) + 2 - tb->lnum[h] - tb->rnum[h] +
144762306a36Sopenharmony_ci		     vn->vn_nr_item + 1) / 2 - (MAX_NR_KEY(Sh) + 1 -
144862306a36Sopenharmony_ci						tb->rnum[h]);
144962306a36Sopenharmony_ci		set_parameters(tb, h, vn->vn_nr_item + 1 - to_r, to_r, 0, NULL,
145062306a36Sopenharmony_ci			       -1, -1);
145162306a36Sopenharmony_ci		return CARRY_ON;
145262306a36Sopenharmony_ci	}
145362306a36Sopenharmony_ci
145462306a36Sopenharmony_ci	/*
145562306a36Sopenharmony_ci	 * this checks balance condition, that any two neighboring nodes
145662306a36Sopenharmony_ci	 * can not fit in one node
145762306a36Sopenharmony_ci	 */
145862306a36Sopenharmony_ci	RFALSE(h &&
145962306a36Sopenharmony_ci	       (tb->lnum[h] >= vn->vn_nr_item + 1 ||
146062306a36Sopenharmony_ci		tb->rnum[h] >= vn->vn_nr_item + 1),
146162306a36Sopenharmony_ci	       "vs-8220: tree is not balanced on internal level");
146262306a36Sopenharmony_ci	RFALSE(!h && ((tb->lnum[h] >= vn->vn_nr_item && (tb->lbytes == -1)) ||
146362306a36Sopenharmony_ci		      (tb->rnum[h] >= vn->vn_nr_item && (tb->rbytes == -1))),
146462306a36Sopenharmony_ci	       "vs-8225: tree is not balanced on leaf level");
146562306a36Sopenharmony_ci
146662306a36Sopenharmony_ci	/*
146762306a36Sopenharmony_ci	 * all contents of S[0] can be moved into its neighbors
146862306a36Sopenharmony_ci	 * S[0] will be removed after balancing.
146962306a36Sopenharmony_ci	 */
147062306a36Sopenharmony_ci	if (!h && is_leaf_removable(tb))
147162306a36Sopenharmony_ci		return CARRY_ON;
147262306a36Sopenharmony_ci
147362306a36Sopenharmony_ci	/*
147462306a36Sopenharmony_ci	 * why do we perform this check here rather than earlier??
147562306a36Sopenharmony_ci	 * Answer: we can win 1 node in some cases above. Moreover we
147662306a36Sopenharmony_ci	 * checked it above, when we checked, that S[0] is not removable
147762306a36Sopenharmony_ci	 * in principle
147862306a36Sopenharmony_ci	 */
147962306a36Sopenharmony_ci
148062306a36Sopenharmony_ci	 /* new item fits into node S[h] without any shifting */
148162306a36Sopenharmony_ci	if (sfree >= levbytes) {
148262306a36Sopenharmony_ci		if (!h)
148362306a36Sopenharmony_ci			tb->s0num = vn->vn_nr_item;
148462306a36Sopenharmony_ci		set_parameters(tb, h, 0, 0, 1, NULL, -1, -1);
148562306a36Sopenharmony_ci		return NO_BALANCING_NEEDED;
148662306a36Sopenharmony_ci	}
148762306a36Sopenharmony_ci
148862306a36Sopenharmony_ci	{
148962306a36Sopenharmony_ci		int lpar, rpar, nset, lset, rset, lrset;
149062306a36Sopenharmony_ci		/* regular overflowing of the node */
149162306a36Sopenharmony_ci
149262306a36Sopenharmony_ci		/*
149362306a36Sopenharmony_ci		 * get_num_ver works in 2 modes (FLOW & NO_FLOW)
149462306a36Sopenharmony_ci		 * lpar, rpar - number of items we can shift to left/right
149562306a36Sopenharmony_ci		 *              neighbor (including splitting item)
149662306a36Sopenharmony_ci		 * nset, lset, rset, lrset - shows, whether flowing items
149762306a36Sopenharmony_ci		 *                           give better packing
149862306a36Sopenharmony_ci		 */
149962306a36Sopenharmony_ci#define FLOW 1
150062306a36Sopenharmony_ci#define NO_FLOW 0		/* do not any splitting */
150162306a36Sopenharmony_ci
150262306a36Sopenharmony_ci		/* we choose one of the following */
150362306a36Sopenharmony_ci#define NOTHING_SHIFT_NO_FLOW	0
150462306a36Sopenharmony_ci#define NOTHING_SHIFT_FLOW	5
150562306a36Sopenharmony_ci#define LEFT_SHIFT_NO_FLOW	10
150662306a36Sopenharmony_ci#define LEFT_SHIFT_FLOW		15
150762306a36Sopenharmony_ci#define RIGHT_SHIFT_NO_FLOW	20
150862306a36Sopenharmony_ci#define RIGHT_SHIFT_FLOW	25
150962306a36Sopenharmony_ci#define LR_SHIFT_NO_FLOW	30
151062306a36Sopenharmony_ci#define LR_SHIFT_FLOW		35
151162306a36Sopenharmony_ci
151262306a36Sopenharmony_ci		lpar = tb->lnum[h];
151362306a36Sopenharmony_ci		rpar = tb->rnum[h];
151462306a36Sopenharmony_ci
151562306a36Sopenharmony_ci		/*
151662306a36Sopenharmony_ci		 * calculate number of blocks S[h] must be split into when
151762306a36Sopenharmony_ci		 * nothing is shifted to the neighbors, as well as number of
151862306a36Sopenharmony_ci		 * items in each part of the split node (s012 numbers),
151962306a36Sopenharmony_ci		 * and number of bytes (s1bytes) of the shared drop which
152062306a36Sopenharmony_ci		 * flow to S1 if any
152162306a36Sopenharmony_ci		 */
152262306a36Sopenharmony_ci		nset = NOTHING_SHIFT_NO_FLOW;
152362306a36Sopenharmony_ci		nver = get_num_ver(vn->vn_mode, tb, h,
152462306a36Sopenharmony_ci				   0, -1, h ? vn->vn_nr_item : 0, -1,
152562306a36Sopenharmony_ci				   snum012, NO_FLOW);
152662306a36Sopenharmony_ci
152762306a36Sopenharmony_ci		if (!h) {
152862306a36Sopenharmony_ci			int nver1;
152962306a36Sopenharmony_ci
153062306a36Sopenharmony_ci			/*
153162306a36Sopenharmony_ci			 * note, that in this case we try to bottle
153262306a36Sopenharmony_ci			 * between S[0] and S1 (S1 - the first new node)
153362306a36Sopenharmony_ci			 */
153462306a36Sopenharmony_ci			nver1 = get_num_ver(vn->vn_mode, tb, h,
153562306a36Sopenharmony_ci					    0, -1, 0, -1,
153662306a36Sopenharmony_ci					    snum012 + NOTHING_SHIFT_FLOW, FLOW);
153762306a36Sopenharmony_ci			if (nver > nver1)
153862306a36Sopenharmony_ci				nset = NOTHING_SHIFT_FLOW, nver = nver1;
153962306a36Sopenharmony_ci		}
154062306a36Sopenharmony_ci
154162306a36Sopenharmony_ci		/*
154262306a36Sopenharmony_ci		 * calculate number of blocks S[h] must be split into when
154362306a36Sopenharmony_ci		 * l_shift_num first items and l_shift_bytes of the right
154462306a36Sopenharmony_ci		 * most liquid item to be shifted are shifted to the left
154562306a36Sopenharmony_ci		 * neighbor, as well as number of items in each part of the
154662306a36Sopenharmony_ci		 * splitted node (s012 numbers), and number of bytes
154762306a36Sopenharmony_ci		 * (s1bytes) of the shared drop which flow to S1 if any
154862306a36Sopenharmony_ci		 */
154962306a36Sopenharmony_ci		lset = LEFT_SHIFT_NO_FLOW;
155062306a36Sopenharmony_ci		lnver = get_num_ver(vn->vn_mode, tb, h,
155162306a36Sopenharmony_ci				    lpar - ((h || tb->lbytes == -1) ? 0 : 1),
155262306a36Sopenharmony_ci				    -1, h ? vn->vn_nr_item : 0, -1,
155362306a36Sopenharmony_ci				    snum012 + LEFT_SHIFT_NO_FLOW, NO_FLOW);
155462306a36Sopenharmony_ci		if (!h) {
155562306a36Sopenharmony_ci			int lnver1;
155662306a36Sopenharmony_ci
155762306a36Sopenharmony_ci			lnver1 = get_num_ver(vn->vn_mode, tb, h,
155862306a36Sopenharmony_ci					     lpar -
155962306a36Sopenharmony_ci					     ((tb->lbytes != -1) ? 1 : 0),
156062306a36Sopenharmony_ci					     tb->lbytes, 0, -1,
156162306a36Sopenharmony_ci					     snum012 + LEFT_SHIFT_FLOW, FLOW);
156262306a36Sopenharmony_ci			if (lnver > lnver1)
156362306a36Sopenharmony_ci				lset = LEFT_SHIFT_FLOW, lnver = lnver1;
156462306a36Sopenharmony_ci		}
156562306a36Sopenharmony_ci
156662306a36Sopenharmony_ci		/*
156762306a36Sopenharmony_ci		 * calculate number of blocks S[h] must be split into when
156862306a36Sopenharmony_ci		 * r_shift_num first items and r_shift_bytes of the left most
156962306a36Sopenharmony_ci		 * liquid item to be shifted are shifted to the right neighbor,
157062306a36Sopenharmony_ci		 * as well as number of items in each part of the splitted
157162306a36Sopenharmony_ci		 * node (s012 numbers), and number of bytes (s1bytes) of the
157262306a36Sopenharmony_ci		 * shared drop which flow to S1 if any
157362306a36Sopenharmony_ci		 */
157462306a36Sopenharmony_ci		rset = RIGHT_SHIFT_NO_FLOW;
157562306a36Sopenharmony_ci		rnver = get_num_ver(vn->vn_mode, tb, h,
157662306a36Sopenharmony_ci				    0, -1,
157762306a36Sopenharmony_ci				    h ? (vn->vn_nr_item - rpar) : (rpar -
157862306a36Sopenharmony_ci								   ((tb->
157962306a36Sopenharmony_ci								     rbytes !=
158062306a36Sopenharmony_ci								     -1) ? 1 :
158162306a36Sopenharmony_ci								    0)), -1,
158262306a36Sopenharmony_ci				    snum012 + RIGHT_SHIFT_NO_FLOW, NO_FLOW);
158362306a36Sopenharmony_ci		if (!h) {
158462306a36Sopenharmony_ci			int rnver1;
158562306a36Sopenharmony_ci
158662306a36Sopenharmony_ci			rnver1 = get_num_ver(vn->vn_mode, tb, h,
158762306a36Sopenharmony_ci					     0, -1,
158862306a36Sopenharmony_ci					     (rpar -
158962306a36Sopenharmony_ci					      ((tb->rbytes != -1) ? 1 : 0)),
159062306a36Sopenharmony_ci					     tb->rbytes,
159162306a36Sopenharmony_ci					     snum012 + RIGHT_SHIFT_FLOW, FLOW);
159262306a36Sopenharmony_ci
159362306a36Sopenharmony_ci			if (rnver > rnver1)
159462306a36Sopenharmony_ci				rset = RIGHT_SHIFT_FLOW, rnver = rnver1;
159562306a36Sopenharmony_ci		}
159662306a36Sopenharmony_ci
159762306a36Sopenharmony_ci		/*
159862306a36Sopenharmony_ci		 * calculate number of blocks S[h] must be split into when
159962306a36Sopenharmony_ci		 * items are shifted in both directions, as well as number
160062306a36Sopenharmony_ci		 * of items in each part of the splitted node (s012 numbers),
160162306a36Sopenharmony_ci		 * and number of bytes (s1bytes) of the shared drop which
160262306a36Sopenharmony_ci		 * flow to S1 if any
160362306a36Sopenharmony_ci		 */
160462306a36Sopenharmony_ci		lrset = LR_SHIFT_NO_FLOW;
160562306a36Sopenharmony_ci		lrnver = get_num_ver(vn->vn_mode, tb, h,
160662306a36Sopenharmony_ci				     lpar - ((h || tb->lbytes == -1) ? 0 : 1),
160762306a36Sopenharmony_ci				     -1,
160862306a36Sopenharmony_ci				     h ? (vn->vn_nr_item - rpar) : (rpar -
160962306a36Sopenharmony_ci								    ((tb->
161062306a36Sopenharmony_ci								      rbytes !=
161162306a36Sopenharmony_ci								      -1) ? 1 :
161262306a36Sopenharmony_ci								     0)), -1,
161362306a36Sopenharmony_ci				     snum012 + LR_SHIFT_NO_FLOW, NO_FLOW);
161462306a36Sopenharmony_ci		if (!h) {
161562306a36Sopenharmony_ci			int lrnver1;
161662306a36Sopenharmony_ci
161762306a36Sopenharmony_ci			lrnver1 = get_num_ver(vn->vn_mode, tb, h,
161862306a36Sopenharmony_ci					      lpar -
161962306a36Sopenharmony_ci					      ((tb->lbytes != -1) ? 1 : 0),
162062306a36Sopenharmony_ci					      tb->lbytes,
162162306a36Sopenharmony_ci					      (rpar -
162262306a36Sopenharmony_ci					       ((tb->rbytes != -1) ? 1 : 0)),
162362306a36Sopenharmony_ci					      tb->rbytes,
162462306a36Sopenharmony_ci					      snum012 + LR_SHIFT_FLOW, FLOW);
162562306a36Sopenharmony_ci			if (lrnver > lrnver1)
162662306a36Sopenharmony_ci				lrset = LR_SHIFT_FLOW, lrnver = lrnver1;
162762306a36Sopenharmony_ci		}
162862306a36Sopenharmony_ci
162962306a36Sopenharmony_ci		/*
163062306a36Sopenharmony_ci		 * Our general shifting strategy is:
163162306a36Sopenharmony_ci		 * 1) to minimized number of new nodes;
163262306a36Sopenharmony_ci		 * 2) to minimized number of neighbors involved in shifting;
163362306a36Sopenharmony_ci		 * 3) to minimized number of disk reads;
163462306a36Sopenharmony_ci		 */
163562306a36Sopenharmony_ci
163662306a36Sopenharmony_ci		/* we can win TWO or ONE nodes by shifting in both directions */
163762306a36Sopenharmony_ci		if (lrnver < lnver && lrnver < rnver) {
163862306a36Sopenharmony_ci			RFALSE(h &&
163962306a36Sopenharmony_ci			       (tb->lnum[h] != 1 ||
164062306a36Sopenharmony_ci				tb->rnum[h] != 1 ||
164162306a36Sopenharmony_ci				lrnver != 1 || rnver != 2 || lnver != 2
164262306a36Sopenharmony_ci				|| h != 1), "vs-8230: bad h");
164362306a36Sopenharmony_ci			if (lrset == LR_SHIFT_FLOW)
164462306a36Sopenharmony_ci				set_parameters(tb, h, tb->lnum[h], tb->rnum[h],
164562306a36Sopenharmony_ci					       lrnver, snum012 + lrset,
164662306a36Sopenharmony_ci					       tb->lbytes, tb->rbytes);
164762306a36Sopenharmony_ci			else
164862306a36Sopenharmony_ci				set_parameters(tb, h,
164962306a36Sopenharmony_ci					       tb->lnum[h] -
165062306a36Sopenharmony_ci					       ((tb->lbytes == -1) ? 0 : 1),
165162306a36Sopenharmony_ci					       tb->rnum[h] -
165262306a36Sopenharmony_ci					       ((tb->rbytes == -1) ? 0 : 1),
165362306a36Sopenharmony_ci					       lrnver, snum012 + lrset, -1, -1);
165462306a36Sopenharmony_ci
165562306a36Sopenharmony_ci			return CARRY_ON;
165662306a36Sopenharmony_ci		}
165762306a36Sopenharmony_ci
165862306a36Sopenharmony_ci		/*
165962306a36Sopenharmony_ci		 * if shifting doesn't lead to better packing
166062306a36Sopenharmony_ci		 * then don't shift
166162306a36Sopenharmony_ci		 */
166262306a36Sopenharmony_ci		if (nver == lrnver) {
166362306a36Sopenharmony_ci			set_parameters(tb, h, 0, 0, nver, snum012 + nset, -1,
166462306a36Sopenharmony_ci				       -1);
166562306a36Sopenharmony_ci			return CARRY_ON;
166662306a36Sopenharmony_ci		}
166762306a36Sopenharmony_ci
166862306a36Sopenharmony_ci		/*
166962306a36Sopenharmony_ci		 * now we know that for better packing shifting in only one
167062306a36Sopenharmony_ci		 * direction either to the left or to the right is required
167162306a36Sopenharmony_ci		 */
167262306a36Sopenharmony_ci
167362306a36Sopenharmony_ci		/*
167462306a36Sopenharmony_ci		 * if shifting to the left is better than
167562306a36Sopenharmony_ci		 * shifting to the right
167662306a36Sopenharmony_ci		 */
167762306a36Sopenharmony_ci		if (lnver < rnver) {
167862306a36Sopenharmony_ci			SET_PAR_SHIFT_LEFT;
167962306a36Sopenharmony_ci			return CARRY_ON;
168062306a36Sopenharmony_ci		}
168162306a36Sopenharmony_ci
168262306a36Sopenharmony_ci		/*
168362306a36Sopenharmony_ci		 * if shifting to the right is better than
168462306a36Sopenharmony_ci		 * shifting to the left
168562306a36Sopenharmony_ci		 */
168662306a36Sopenharmony_ci		if (lnver > rnver) {
168762306a36Sopenharmony_ci			SET_PAR_SHIFT_RIGHT;
168862306a36Sopenharmony_ci			return CARRY_ON;
168962306a36Sopenharmony_ci		}
169062306a36Sopenharmony_ci
169162306a36Sopenharmony_ci		/*
169262306a36Sopenharmony_ci		 * now shifting in either direction gives the same number
169362306a36Sopenharmony_ci		 * of nodes and we can make use of the cached neighbors
169462306a36Sopenharmony_ci		 */
169562306a36Sopenharmony_ci		if (is_left_neighbor_in_cache(tb, h)) {
169662306a36Sopenharmony_ci			SET_PAR_SHIFT_LEFT;
169762306a36Sopenharmony_ci			return CARRY_ON;
169862306a36Sopenharmony_ci		}
169962306a36Sopenharmony_ci
170062306a36Sopenharmony_ci		/*
170162306a36Sopenharmony_ci		 * shift to the right independently on whether the
170262306a36Sopenharmony_ci		 * right neighbor in cache or not
170362306a36Sopenharmony_ci		 */
170462306a36Sopenharmony_ci		SET_PAR_SHIFT_RIGHT;
170562306a36Sopenharmony_ci		return CARRY_ON;
170662306a36Sopenharmony_ci	}
170762306a36Sopenharmony_ci}
170862306a36Sopenharmony_ci
170962306a36Sopenharmony_ci/*
171062306a36Sopenharmony_ci * Check whether current node S[h] is balanced when Decreasing its size by
171162306a36Sopenharmony_ci * Deleting or Cutting for INTERNAL node of S+tree.
171262306a36Sopenharmony_ci * Calculate parameters for balancing for current level h.
171362306a36Sopenharmony_ci * Parameters:
171462306a36Sopenharmony_ci *	tb	tree_balance structure;
171562306a36Sopenharmony_ci *	h	current level of the node;
171662306a36Sopenharmony_ci *	inum	item number in S[h];
171762306a36Sopenharmony_ci *	mode	i - insert, p - paste;
171862306a36Sopenharmony_ci * Returns:	1 - schedule occurred;
171962306a36Sopenharmony_ci *	        0 - balancing for higher levels needed;
172062306a36Sopenharmony_ci *	       -1 - no balancing for higher levels needed;
172162306a36Sopenharmony_ci *	       -2 - no disk space.
172262306a36Sopenharmony_ci *
172362306a36Sopenharmony_ci * Note: Items of internal nodes have fixed size, so the balance condition for
172462306a36Sopenharmony_ci * the internal part of S+tree is as for the B-trees.
172562306a36Sopenharmony_ci */
172662306a36Sopenharmony_cistatic int dc_check_balance_internal(struct tree_balance *tb, int h)
172762306a36Sopenharmony_ci{
172862306a36Sopenharmony_ci	struct virtual_node *vn = tb->tb_vn;
172962306a36Sopenharmony_ci
173062306a36Sopenharmony_ci	/*
173162306a36Sopenharmony_ci	 * Sh is the node whose balance is currently being checked,
173262306a36Sopenharmony_ci	 * and Fh is its father.
173362306a36Sopenharmony_ci	 */
173462306a36Sopenharmony_ci	struct buffer_head *Sh, *Fh;
173562306a36Sopenharmony_ci	int ret;
173662306a36Sopenharmony_ci	int lfree, rfree /* free space in L and R */ ;
173762306a36Sopenharmony_ci
173862306a36Sopenharmony_ci	Sh = PATH_H_PBUFFER(tb->tb_path, h);
173962306a36Sopenharmony_ci	Fh = PATH_H_PPARENT(tb->tb_path, h);
174062306a36Sopenharmony_ci
174162306a36Sopenharmony_ci	/*
174262306a36Sopenharmony_ci	 * using tb->insert_size[h], which is negative in this case,
174362306a36Sopenharmony_ci	 * create_virtual_node calculates:
174462306a36Sopenharmony_ci	 * new_nr_item = number of items node would have if operation is
174562306a36Sopenharmony_ci	 * performed without balancing (new_nr_item);
174662306a36Sopenharmony_ci	 */
174762306a36Sopenharmony_ci	create_virtual_node(tb, h);
174862306a36Sopenharmony_ci
174962306a36Sopenharmony_ci	if (!Fh) {		/* S[h] is the root. */
175062306a36Sopenharmony_ci		/* no balancing for higher levels needed */
175162306a36Sopenharmony_ci		if (vn->vn_nr_item > 0) {
175262306a36Sopenharmony_ci			set_parameters(tb, h, 0, 0, 1, NULL, -1, -1);
175362306a36Sopenharmony_ci			return NO_BALANCING_NEEDED;
175462306a36Sopenharmony_ci		}
175562306a36Sopenharmony_ci		/*
175662306a36Sopenharmony_ci		 * new_nr_item == 0.
175762306a36Sopenharmony_ci		 * Current root will be deleted resulting in
175862306a36Sopenharmony_ci		 * decrementing the tree height.
175962306a36Sopenharmony_ci		 */
176062306a36Sopenharmony_ci		set_parameters(tb, h, 0, 0, 0, NULL, -1, -1);
176162306a36Sopenharmony_ci		return CARRY_ON;
176262306a36Sopenharmony_ci	}
176362306a36Sopenharmony_ci
176462306a36Sopenharmony_ci	if ((ret = get_parents(tb, h)) != CARRY_ON)
176562306a36Sopenharmony_ci		return ret;
176662306a36Sopenharmony_ci
176762306a36Sopenharmony_ci	/* get free space of neighbors */
176862306a36Sopenharmony_ci	rfree = get_rfree(tb, h);
176962306a36Sopenharmony_ci	lfree = get_lfree(tb, h);
177062306a36Sopenharmony_ci
177162306a36Sopenharmony_ci	/* determine maximal number of items we can fit into neighbors */
177262306a36Sopenharmony_ci	check_left(tb, h, lfree);
177362306a36Sopenharmony_ci	check_right(tb, h, rfree);
177462306a36Sopenharmony_ci
177562306a36Sopenharmony_ci	/*
177662306a36Sopenharmony_ci	 * Balance condition for the internal node is valid.
177762306a36Sopenharmony_ci	 * In this case we balance only if it leads to better packing.
177862306a36Sopenharmony_ci	 */
177962306a36Sopenharmony_ci	if (vn->vn_nr_item >= MIN_NR_KEY(Sh)) {
178062306a36Sopenharmony_ci		/*
178162306a36Sopenharmony_ci		 * Here we join S[h] with one of its neighbors,
178262306a36Sopenharmony_ci		 * which is impossible with greater values of new_nr_item.
178362306a36Sopenharmony_ci		 */
178462306a36Sopenharmony_ci		if (vn->vn_nr_item == MIN_NR_KEY(Sh)) {
178562306a36Sopenharmony_ci			/* All contents of S[h] can be moved to L[h]. */
178662306a36Sopenharmony_ci			if (tb->lnum[h] >= vn->vn_nr_item + 1) {
178762306a36Sopenharmony_ci				int n;
178862306a36Sopenharmony_ci				int order_L;
178962306a36Sopenharmony_ci
179062306a36Sopenharmony_ci				order_L =
179162306a36Sopenharmony_ci				    ((n =
179262306a36Sopenharmony_ci				      PATH_H_B_ITEM_ORDER(tb->tb_path,
179362306a36Sopenharmony_ci							  h)) ==
179462306a36Sopenharmony_ci				     0) ? B_NR_ITEMS(tb->FL[h]) : n - 1;
179562306a36Sopenharmony_ci				n = dc_size(B_N_CHILD(tb->FL[h], order_L)) /
179662306a36Sopenharmony_ci				    (DC_SIZE + KEY_SIZE);
179762306a36Sopenharmony_ci				set_parameters(tb, h, -n - 1, 0, 0, NULL, -1,
179862306a36Sopenharmony_ci					       -1);
179962306a36Sopenharmony_ci				return CARRY_ON;
180062306a36Sopenharmony_ci			}
180162306a36Sopenharmony_ci
180262306a36Sopenharmony_ci			/* All contents of S[h] can be moved to R[h]. */
180362306a36Sopenharmony_ci			if (tb->rnum[h] >= vn->vn_nr_item + 1) {
180462306a36Sopenharmony_ci				int n;
180562306a36Sopenharmony_ci				int order_R;
180662306a36Sopenharmony_ci
180762306a36Sopenharmony_ci				order_R =
180862306a36Sopenharmony_ci				    ((n =
180962306a36Sopenharmony_ci				      PATH_H_B_ITEM_ORDER(tb->tb_path,
181062306a36Sopenharmony_ci							  h)) ==
181162306a36Sopenharmony_ci				     B_NR_ITEMS(Fh)) ? 0 : n + 1;
181262306a36Sopenharmony_ci				n = dc_size(B_N_CHILD(tb->FR[h], order_R)) /
181362306a36Sopenharmony_ci				    (DC_SIZE + KEY_SIZE);
181462306a36Sopenharmony_ci				set_parameters(tb, h, 0, -n - 1, 0, NULL, -1,
181562306a36Sopenharmony_ci					       -1);
181662306a36Sopenharmony_ci				return CARRY_ON;
181762306a36Sopenharmony_ci			}
181862306a36Sopenharmony_ci		}
181962306a36Sopenharmony_ci
182062306a36Sopenharmony_ci		/*
182162306a36Sopenharmony_ci		 * All contents of S[h] can be moved to the neighbors
182262306a36Sopenharmony_ci		 * (L[h] & R[h]).
182362306a36Sopenharmony_ci		 */
182462306a36Sopenharmony_ci		if (tb->rnum[h] + tb->lnum[h] >= vn->vn_nr_item + 1) {
182562306a36Sopenharmony_ci			int to_r;
182662306a36Sopenharmony_ci
182762306a36Sopenharmony_ci			to_r =
182862306a36Sopenharmony_ci			    ((MAX_NR_KEY(Sh) << 1) + 2 - tb->lnum[h] -
182962306a36Sopenharmony_ci			     tb->rnum[h] + vn->vn_nr_item + 1) / 2 -
183062306a36Sopenharmony_ci			    (MAX_NR_KEY(Sh) + 1 - tb->rnum[h]);
183162306a36Sopenharmony_ci			set_parameters(tb, h, vn->vn_nr_item + 1 - to_r, to_r,
183262306a36Sopenharmony_ci				       0, NULL, -1, -1);
183362306a36Sopenharmony_ci			return CARRY_ON;
183462306a36Sopenharmony_ci		}
183562306a36Sopenharmony_ci
183662306a36Sopenharmony_ci		/* Balancing does not lead to better packing. */
183762306a36Sopenharmony_ci		set_parameters(tb, h, 0, 0, 1, NULL, -1, -1);
183862306a36Sopenharmony_ci		return NO_BALANCING_NEEDED;
183962306a36Sopenharmony_ci	}
184062306a36Sopenharmony_ci
184162306a36Sopenharmony_ci	/*
184262306a36Sopenharmony_ci	 * Current node contain insufficient number of items.
184362306a36Sopenharmony_ci	 * Balancing is required.
184462306a36Sopenharmony_ci	 */
184562306a36Sopenharmony_ci	/* Check whether we can merge S[h] with left neighbor. */
184662306a36Sopenharmony_ci	if (tb->lnum[h] >= vn->vn_nr_item + 1)
184762306a36Sopenharmony_ci		if (is_left_neighbor_in_cache(tb, h)
184862306a36Sopenharmony_ci		    || tb->rnum[h] < vn->vn_nr_item + 1 || !tb->FR[h]) {
184962306a36Sopenharmony_ci			int n;
185062306a36Sopenharmony_ci			int order_L;
185162306a36Sopenharmony_ci
185262306a36Sopenharmony_ci			order_L =
185362306a36Sopenharmony_ci			    ((n =
185462306a36Sopenharmony_ci			      PATH_H_B_ITEM_ORDER(tb->tb_path,
185562306a36Sopenharmony_ci						  h)) ==
185662306a36Sopenharmony_ci			     0) ? B_NR_ITEMS(tb->FL[h]) : n - 1;
185762306a36Sopenharmony_ci			n = dc_size(B_N_CHILD(tb->FL[h], order_L)) / (DC_SIZE +
185862306a36Sopenharmony_ci								      KEY_SIZE);
185962306a36Sopenharmony_ci			set_parameters(tb, h, -n - 1, 0, 0, NULL, -1, -1);
186062306a36Sopenharmony_ci			return CARRY_ON;
186162306a36Sopenharmony_ci		}
186262306a36Sopenharmony_ci
186362306a36Sopenharmony_ci	/* Check whether we can merge S[h] with right neighbor. */
186462306a36Sopenharmony_ci	if (tb->rnum[h] >= vn->vn_nr_item + 1) {
186562306a36Sopenharmony_ci		int n;
186662306a36Sopenharmony_ci		int order_R;
186762306a36Sopenharmony_ci
186862306a36Sopenharmony_ci		order_R =
186962306a36Sopenharmony_ci		    ((n =
187062306a36Sopenharmony_ci		      PATH_H_B_ITEM_ORDER(tb->tb_path,
187162306a36Sopenharmony_ci					  h)) == B_NR_ITEMS(Fh)) ? 0 : (n + 1);
187262306a36Sopenharmony_ci		n = dc_size(B_N_CHILD(tb->FR[h], order_R)) / (DC_SIZE +
187362306a36Sopenharmony_ci							      KEY_SIZE);
187462306a36Sopenharmony_ci		set_parameters(tb, h, 0, -n - 1, 0, NULL, -1, -1);
187562306a36Sopenharmony_ci		return CARRY_ON;
187662306a36Sopenharmony_ci	}
187762306a36Sopenharmony_ci
187862306a36Sopenharmony_ci	/* All contents of S[h] can be moved to the neighbors (L[h] & R[h]). */
187962306a36Sopenharmony_ci	if (tb->rnum[h] + tb->lnum[h] >= vn->vn_nr_item + 1) {
188062306a36Sopenharmony_ci		int to_r;
188162306a36Sopenharmony_ci
188262306a36Sopenharmony_ci		to_r =
188362306a36Sopenharmony_ci		    ((MAX_NR_KEY(Sh) << 1) + 2 - tb->lnum[h] - tb->rnum[h] +
188462306a36Sopenharmony_ci		     vn->vn_nr_item + 1) / 2 - (MAX_NR_KEY(Sh) + 1 -
188562306a36Sopenharmony_ci						tb->rnum[h]);
188662306a36Sopenharmony_ci		set_parameters(tb, h, vn->vn_nr_item + 1 - to_r, to_r, 0, NULL,
188762306a36Sopenharmony_ci			       -1, -1);
188862306a36Sopenharmony_ci		return CARRY_ON;
188962306a36Sopenharmony_ci	}
189062306a36Sopenharmony_ci
189162306a36Sopenharmony_ci	/* For internal nodes try to borrow item from a neighbor */
189262306a36Sopenharmony_ci	RFALSE(!tb->FL[h] && !tb->FR[h], "vs-8235: trying to borrow for root");
189362306a36Sopenharmony_ci
189462306a36Sopenharmony_ci	/* Borrow one or two items from caching neighbor */
189562306a36Sopenharmony_ci	if (is_left_neighbor_in_cache(tb, h) || !tb->FR[h]) {
189662306a36Sopenharmony_ci		int from_l;
189762306a36Sopenharmony_ci
189862306a36Sopenharmony_ci		from_l =
189962306a36Sopenharmony_ci		    (MAX_NR_KEY(Sh) + 1 - tb->lnum[h] + vn->vn_nr_item +
190062306a36Sopenharmony_ci		     1) / 2 - (vn->vn_nr_item + 1);
190162306a36Sopenharmony_ci		set_parameters(tb, h, -from_l, 0, 1, NULL, -1, -1);
190262306a36Sopenharmony_ci		return CARRY_ON;
190362306a36Sopenharmony_ci	}
190462306a36Sopenharmony_ci
190562306a36Sopenharmony_ci	set_parameters(tb, h, 0,
190662306a36Sopenharmony_ci		       -((MAX_NR_KEY(Sh) + 1 - tb->rnum[h] + vn->vn_nr_item +
190762306a36Sopenharmony_ci			  1) / 2 - (vn->vn_nr_item + 1)), 1, NULL, -1, -1);
190862306a36Sopenharmony_ci	return CARRY_ON;
190962306a36Sopenharmony_ci}
191062306a36Sopenharmony_ci
191162306a36Sopenharmony_ci/*
191262306a36Sopenharmony_ci * Check whether current node S[h] is balanced when Decreasing its size by
191362306a36Sopenharmony_ci * Deleting or Truncating for LEAF node of S+tree.
191462306a36Sopenharmony_ci * Calculate parameters for balancing for current level h.
191562306a36Sopenharmony_ci * Parameters:
191662306a36Sopenharmony_ci *	tb	tree_balance structure;
191762306a36Sopenharmony_ci *	h	current level of the node;
191862306a36Sopenharmony_ci *	inum	item number in S[h];
191962306a36Sopenharmony_ci *	mode	i - insert, p - paste;
192062306a36Sopenharmony_ci * Returns:	1 - schedule occurred;
192162306a36Sopenharmony_ci *	        0 - balancing for higher levels needed;
192262306a36Sopenharmony_ci *	       -1 - no balancing for higher levels needed;
192362306a36Sopenharmony_ci *	       -2 - no disk space.
192462306a36Sopenharmony_ci */
192562306a36Sopenharmony_cistatic int dc_check_balance_leaf(struct tree_balance *tb, int h)
192662306a36Sopenharmony_ci{
192762306a36Sopenharmony_ci	struct virtual_node *vn = tb->tb_vn;
192862306a36Sopenharmony_ci
192962306a36Sopenharmony_ci	/*
193062306a36Sopenharmony_ci	 * Number of bytes that must be deleted from
193162306a36Sopenharmony_ci	 * (value is negative if bytes are deleted) buffer which
193262306a36Sopenharmony_ci	 * contains node being balanced.  The mnemonic is that the
193362306a36Sopenharmony_ci	 * attempted change in node space used level is levbytes bytes.
193462306a36Sopenharmony_ci	 */
193562306a36Sopenharmony_ci	int levbytes;
193662306a36Sopenharmony_ci
193762306a36Sopenharmony_ci	/* the maximal item size */
193862306a36Sopenharmony_ci	int maxsize, ret;
193962306a36Sopenharmony_ci
194062306a36Sopenharmony_ci	/*
194162306a36Sopenharmony_ci	 * S0 is the node whose balance is currently being checked,
194262306a36Sopenharmony_ci	 * and F0 is its father.
194362306a36Sopenharmony_ci	 */
194462306a36Sopenharmony_ci	struct buffer_head *S0, *F0;
194562306a36Sopenharmony_ci	int lfree, rfree /* free space in L and R */ ;
194662306a36Sopenharmony_ci
194762306a36Sopenharmony_ci	S0 = PATH_H_PBUFFER(tb->tb_path, 0);
194862306a36Sopenharmony_ci	F0 = PATH_H_PPARENT(tb->tb_path, 0);
194962306a36Sopenharmony_ci
195062306a36Sopenharmony_ci	levbytes = tb->insert_size[h];
195162306a36Sopenharmony_ci
195262306a36Sopenharmony_ci	maxsize = MAX_CHILD_SIZE(S0);	/* maximal possible size of an item */
195362306a36Sopenharmony_ci
195462306a36Sopenharmony_ci	if (!F0) {		/* S[0] is the root now. */
195562306a36Sopenharmony_ci
195662306a36Sopenharmony_ci		RFALSE(-levbytes >= maxsize - B_FREE_SPACE(S0),
195762306a36Sopenharmony_ci		       "vs-8240: attempt to create empty buffer tree");
195862306a36Sopenharmony_ci
195962306a36Sopenharmony_ci		set_parameters(tb, h, 0, 0, 1, NULL, -1, -1);
196062306a36Sopenharmony_ci		return NO_BALANCING_NEEDED;
196162306a36Sopenharmony_ci	}
196262306a36Sopenharmony_ci
196362306a36Sopenharmony_ci	if ((ret = get_parents(tb, h)) != CARRY_ON)
196462306a36Sopenharmony_ci		return ret;
196562306a36Sopenharmony_ci
196662306a36Sopenharmony_ci	/* get free space of neighbors */
196762306a36Sopenharmony_ci	rfree = get_rfree(tb, h);
196862306a36Sopenharmony_ci	lfree = get_lfree(tb, h);
196962306a36Sopenharmony_ci
197062306a36Sopenharmony_ci	create_virtual_node(tb, h);
197162306a36Sopenharmony_ci
197262306a36Sopenharmony_ci	/* if 3 leaves can be merge to one, set parameters and return */
197362306a36Sopenharmony_ci	if (are_leaves_removable(tb, lfree, rfree))
197462306a36Sopenharmony_ci		return CARRY_ON;
197562306a36Sopenharmony_ci
197662306a36Sopenharmony_ci	/*
197762306a36Sopenharmony_ci	 * determine maximal number of items we can shift to the left/right
197862306a36Sopenharmony_ci	 * neighbor and the maximal number of bytes that can flow to the
197962306a36Sopenharmony_ci	 * left/right neighbor from the left/right most liquid item that
198062306a36Sopenharmony_ci	 * cannot be shifted from S[0] entirely
198162306a36Sopenharmony_ci	 */
198262306a36Sopenharmony_ci	check_left(tb, h, lfree);
198362306a36Sopenharmony_ci	check_right(tb, h, rfree);
198462306a36Sopenharmony_ci
198562306a36Sopenharmony_ci	/* check whether we can merge S with left neighbor. */
198662306a36Sopenharmony_ci	if (tb->lnum[0] >= vn->vn_nr_item && tb->lbytes == -1)
198762306a36Sopenharmony_ci		if (is_left_neighbor_in_cache(tb, h) || ((tb->rnum[0] - ((tb->rbytes == -1) ? 0 : 1)) < vn->vn_nr_item) ||	/* S can not be merged with R */
198862306a36Sopenharmony_ci		    !tb->FR[h]) {
198962306a36Sopenharmony_ci
199062306a36Sopenharmony_ci			RFALSE(!tb->FL[h],
199162306a36Sopenharmony_ci			       "vs-8245: dc_check_balance_leaf: FL[h] must exist");
199262306a36Sopenharmony_ci
199362306a36Sopenharmony_ci			/* set parameter to merge S[0] with its left neighbor */
199462306a36Sopenharmony_ci			set_parameters(tb, h, -1, 0, 0, NULL, -1, -1);
199562306a36Sopenharmony_ci			return CARRY_ON;
199662306a36Sopenharmony_ci		}
199762306a36Sopenharmony_ci
199862306a36Sopenharmony_ci	/* check whether we can merge S[0] with right neighbor. */
199962306a36Sopenharmony_ci	if (tb->rnum[0] >= vn->vn_nr_item && tb->rbytes == -1) {
200062306a36Sopenharmony_ci		set_parameters(tb, h, 0, -1, 0, NULL, -1, -1);
200162306a36Sopenharmony_ci		return CARRY_ON;
200262306a36Sopenharmony_ci	}
200362306a36Sopenharmony_ci
200462306a36Sopenharmony_ci	/*
200562306a36Sopenharmony_ci	 * All contents of S[0] can be moved to the neighbors (L[0] & R[0]).
200662306a36Sopenharmony_ci	 * Set parameters and return
200762306a36Sopenharmony_ci	 */
200862306a36Sopenharmony_ci	if (is_leaf_removable(tb))
200962306a36Sopenharmony_ci		return CARRY_ON;
201062306a36Sopenharmony_ci
201162306a36Sopenharmony_ci	/* Balancing is not required. */
201262306a36Sopenharmony_ci	tb->s0num = vn->vn_nr_item;
201362306a36Sopenharmony_ci	set_parameters(tb, h, 0, 0, 1, NULL, -1, -1);
201462306a36Sopenharmony_ci	return NO_BALANCING_NEEDED;
201562306a36Sopenharmony_ci}
201662306a36Sopenharmony_ci
201762306a36Sopenharmony_ci/*
201862306a36Sopenharmony_ci * Check whether current node S[h] is balanced when Decreasing its size by
201962306a36Sopenharmony_ci * Deleting or Cutting.
202062306a36Sopenharmony_ci * Calculate parameters for balancing for current level h.
202162306a36Sopenharmony_ci * Parameters:
202262306a36Sopenharmony_ci *	tb	tree_balance structure;
202362306a36Sopenharmony_ci *	h	current level of the node;
202462306a36Sopenharmony_ci *	inum	item number in S[h];
202562306a36Sopenharmony_ci *	mode	d - delete, c - cut.
202662306a36Sopenharmony_ci * Returns:	1 - schedule occurred;
202762306a36Sopenharmony_ci *	        0 - balancing for higher levels needed;
202862306a36Sopenharmony_ci *	       -1 - no balancing for higher levels needed;
202962306a36Sopenharmony_ci *	       -2 - no disk space.
203062306a36Sopenharmony_ci */
203162306a36Sopenharmony_cistatic int dc_check_balance(struct tree_balance *tb, int h)
203262306a36Sopenharmony_ci{
203362306a36Sopenharmony_ci	RFALSE(!(PATH_H_PBUFFER(tb->tb_path, h)),
203462306a36Sopenharmony_ci	       "vs-8250: S is not initialized");
203562306a36Sopenharmony_ci
203662306a36Sopenharmony_ci	if (h)
203762306a36Sopenharmony_ci		return dc_check_balance_internal(tb, h);
203862306a36Sopenharmony_ci	else
203962306a36Sopenharmony_ci		return dc_check_balance_leaf(tb, h);
204062306a36Sopenharmony_ci}
204162306a36Sopenharmony_ci
204262306a36Sopenharmony_ci/*
204362306a36Sopenharmony_ci * Check whether current node S[h] is balanced.
204462306a36Sopenharmony_ci * Calculate parameters for balancing for current level h.
204562306a36Sopenharmony_ci * Parameters:
204662306a36Sopenharmony_ci *
204762306a36Sopenharmony_ci *	tb	tree_balance structure:
204862306a36Sopenharmony_ci *
204962306a36Sopenharmony_ci *              tb is a large structure that must be read about in the header
205062306a36Sopenharmony_ci *		file at the same time as this procedure if the reader is
205162306a36Sopenharmony_ci *		to successfully understand this procedure
205262306a36Sopenharmony_ci *
205362306a36Sopenharmony_ci *	h	current level of the node;
205462306a36Sopenharmony_ci *	inum	item number in S[h];
205562306a36Sopenharmony_ci *	mode	i - insert, p - paste, d - delete, c - cut.
205662306a36Sopenharmony_ci * Returns:	1 - schedule occurred;
205762306a36Sopenharmony_ci *	        0 - balancing for higher levels needed;
205862306a36Sopenharmony_ci *	       -1 - no balancing for higher levels needed;
205962306a36Sopenharmony_ci *	       -2 - no disk space.
206062306a36Sopenharmony_ci */
206162306a36Sopenharmony_cistatic int check_balance(int mode,
206262306a36Sopenharmony_ci			 struct tree_balance *tb,
206362306a36Sopenharmony_ci			 int h,
206462306a36Sopenharmony_ci			 int inum,
206562306a36Sopenharmony_ci			 int pos_in_item,
206662306a36Sopenharmony_ci			 struct item_head *ins_ih, const void *data)
206762306a36Sopenharmony_ci{
206862306a36Sopenharmony_ci	struct virtual_node *vn;
206962306a36Sopenharmony_ci
207062306a36Sopenharmony_ci	vn = tb->tb_vn = (struct virtual_node *)(tb->vn_buf);
207162306a36Sopenharmony_ci	vn->vn_free_ptr = (char *)(tb->tb_vn + 1);
207262306a36Sopenharmony_ci	vn->vn_mode = mode;
207362306a36Sopenharmony_ci	vn->vn_affected_item_num = inum;
207462306a36Sopenharmony_ci	vn->vn_pos_in_item = pos_in_item;
207562306a36Sopenharmony_ci	vn->vn_ins_ih = ins_ih;
207662306a36Sopenharmony_ci	vn->vn_data = data;
207762306a36Sopenharmony_ci
207862306a36Sopenharmony_ci	RFALSE(mode == M_INSERT && !vn->vn_ins_ih,
207962306a36Sopenharmony_ci	       "vs-8255: ins_ih can not be 0 in insert mode");
208062306a36Sopenharmony_ci
208162306a36Sopenharmony_ci	/* Calculate balance parameters when size of node is increasing. */
208262306a36Sopenharmony_ci	if (tb->insert_size[h] > 0)
208362306a36Sopenharmony_ci		return ip_check_balance(tb, h);
208462306a36Sopenharmony_ci
208562306a36Sopenharmony_ci	/* Calculate balance parameters when  size of node is decreasing. */
208662306a36Sopenharmony_ci	return dc_check_balance(tb, h);
208762306a36Sopenharmony_ci}
208862306a36Sopenharmony_ci
208962306a36Sopenharmony_ci/* Check whether parent at the path is the really parent of the current node.*/
209062306a36Sopenharmony_cistatic int get_direct_parent(struct tree_balance *tb, int h)
209162306a36Sopenharmony_ci{
209262306a36Sopenharmony_ci	struct buffer_head *bh;
209362306a36Sopenharmony_ci	struct treepath *path = tb->tb_path;
209462306a36Sopenharmony_ci	int position,
209562306a36Sopenharmony_ci	    path_offset = PATH_H_PATH_OFFSET(tb->tb_path, h);
209662306a36Sopenharmony_ci
209762306a36Sopenharmony_ci	/* We are in the root or in the new root. */
209862306a36Sopenharmony_ci	if (path_offset <= FIRST_PATH_ELEMENT_OFFSET) {
209962306a36Sopenharmony_ci
210062306a36Sopenharmony_ci		RFALSE(path_offset < FIRST_PATH_ELEMENT_OFFSET - 1,
210162306a36Sopenharmony_ci		       "PAP-8260: invalid offset in the path");
210262306a36Sopenharmony_ci
210362306a36Sopenharmony_ci		if (PATH_OFFSET_PBUFFER(path, FIRST_PATH_ELEMENT_OFFSET)->
210462306a36Sopenharmony_ci		    b_blocknr == SB_ROOT_BLOCK(tb->tb_sb)) {
210562306a36Sopenharmony_ci			/* Root is not changed. */
210662306a36Sopenharmony_ci			PATH_OFFSET_PBUFFER(path, path_offset - 1) = NULL;
210762306a36Sopenharmony_ci			PATH_OFFSET_POSITION(path, path_offset - 1) = 0;
210862306a36Sopenharmony_ci			return CARRY_ON;
210962306a36Sopenharmony_ci		}
211062306a36Sopenharmony_ci		/* Root is changed and we must recalculate the path. */
211162306a36Sopenharmony_ci		return REPEAT_SEARCH;
211262306a36Sopenharmony_ci	}
211362306a36Sopenharmony_ci
211462306a36Sopenharmony_ci	/* Parent in the path is not in the tree. */
211562306a36Sopenharmony_ci	if (!B_IS_IN_TREE
211662306a36Sopenharmony_ci	    (bh = PATH_OFFSET_PBUFFER(path, path_offset - 1)))
211762306a36Sopenharmony_ci		return REPEAT_SEARCH;
211862306a36Sopenharmony_ci
211962306a36Sopenharmony_ci	if ((position =
212062306a36Sopenharmony_ci	     PATH_OFFSET_POSITION(path,
212162306a36Sopenharmony_ci				  path_offset - 1)) > B_NR_ITEMS(bh))
212262306a36Sopenharmony_ci		return REPEAT_SEARCH;
212362306a36Sopenharmony_ci
212462306a36Sopenharmony_ci	/* Parent in the path is not parent of the current node in the tree. */
212562306a36Sopenharmony_ci	if (B_N_CHILD_NUM(bh, position) !=
212662306a36Sopenharmony_ci	    PATH_OFFSET_PBUFFER(path, path_offset)->b_blocknr)
212762306a36Sopenharmony_ci		return REPEAT_SEARCH;
212862306a36Sopenharmony_ci
212962306a36Sopenharmony_ci	if (buffer_locked(bh)) {
213062306a36Sopenharmony_ci		int depth = reiserfs_write_unlock_nested(tb->tb_sb);
213162306a36Sopenharmony_ci		__wait_on_buffer(bh);
213262306a36Sopenharmony_ci		reiserfs_write_lock_nested(tb->tb_sb, depth);
213362306a36Sopenharmony_ci		if (FILESYSTEM_CHANGED_TB(tb))
213462306a36Sopenharmony_ci			return REPEAT_SEARCH;
213562306a36Sopenharmony_ci	}
213662306a36Sopenharmony_ci
213762306a36Sopenharmony_ci	/*
213862306a36Sopenharmony_ci	 * Parent in the path is unlocked and really parent
213962306a36Sopenharmony_ci	 * of the current node.
214062306a36Sopenharmony_ci	 */
214162306a36Sopenharmony_ci	return CARRY_ON;
214262306a36Sopenharmony_ci}
214362306a36Sopenharmony_ci
214462306a36Sopenharmony_ci/*
214562306a36Sopenharmony_ci * Using lnum[h] and rnum[h] we should determine what neighbors
214662306a36Sopenharmony_ci * of S[h] we
214762306a36Sopenharmony_ci * need in order to balance S[h], and get them if necessary.
214862306a36Sopenharmony_ci * Returns:	SCHEDULE_OCCURRED - schedule occurred while the function worked;
214962306a36Sopenharmony_ci *	        CARRY_ON - schedule didn't occur while the function worked;
215062306a36Sopenharmony_ci */
215162306a36Sopenharmony_cistatic int get_neighbors(struct tree_balance *tb, int h)
215262306a36Sopenharmony_ci{
215362306a36Sopenharmony_ci	int child_position,
215462306a36Sopenharmony_ci	    path_offset = PATH_H_PATH_OFFSET(tb->tb_path, h + 1);
215562306a36Sopenharmony_ci	unsigned long son_number;
215662306a36Sopenharmony_ci	struct super_block *sb = tb->tb_sb;
215762306a36Sopenharmony_ci	struct buffer_head *bh;
215862306a36Sopenharmony_ci	int depth;
215962306a36Sopenharmony_ci
216062306a36Sopenharmony_ci	PROC_INFO_INC(sb, get_neighbors[h]);
216162306a36Sopenharmony_ci
216262306a36Sopenharmony_ci	if (tb->lnum[h]) {
216362306a36Sopenharmony_ci		/* We need left neighbor to balance S[h]. */
216462306a36Sopenharmony_ci		PROC_INFO_INC(sb, need_l_neighbor[h]);
216562306a36Sopenharmony_ci		bh = PATH_OFFSET_PBUFFER(tb->tb_path, path_offset);
216662306a36Sopenharmony_ci
216762306a36Sopenharmony_ci		RFALSE(bh == tb->FL[h] &&
216862306a36Sopenharmony_ci		       !PATH_OFFSET_POSITION(tb->tb_path, path_offset),
216962306a36Sopenharmony_ci		       "PAP-8270: invalid position in the parent");
217062306a36Sopenharmony_ci
217162306a36Sopenharmony_ci		child_position =
217262306a36Sopenharmony_ci		    (bh ==
217362306a36Sopenharmony_ci		     tb->FL[h]) ? tb->lkey[h] : B_NR_ITEMS(tb->
217462306a36Sopenharmony_ci								       FL[h]);
217562306a36Sopenharmony_ci		son_number = B_N_CHILD_NUM(tb->FL[h], child_position);
217662306a36Sopenharmony_ci		depth = reiserfs_write_unlock_nested(tb->tb_sb);
217762306a36Sopenharmony_ci		bh = sb_bread(sb, son_number);
217862306a36Sopenharmony_ci		reiserfs_write_lock_nested(tb->tb_sb, depth);
217962306a36Sopenharmony_ci		if (!bh)
218062306a36Sopenharmony_ci			return IO_ERROR;
218162306a36Sopenharmony_ci		if (FILESYSTEM_CHANGED_TB(tb)) {
218262306a36Sopenharmony_ci			brelse(bh);
218362306a36Sopenharmony_ci			PROC_INFO_INC(sb, get_neighbors_restart[h]);
218462306a36Sopenharmony_ci			return REPEAT_SEARCH;
218562306a36Sopenharmony_ci		}
218662306a36Sopenharmony_ci
218762306a36Sopenharmony_ci		RFALSE(!B_IS_IN_TREE(tb->FL[h]) ||
218862306a36Sopenharmony_ci		       child_position > B_NR_ITEMS(tb->FL[h]) ||
218962306a36Sopenharmony_ci		       B_N_CHILD_NUM(tb->FL[h], child_position) !=
219062306a36Sopenharmony_ci		       bh->b_blocknr, "PAP-8275: invalid parent");
219162306a36Sopenharmony_ci		RFALSE(!B_IS_IN_TREE(bh), "PAP-8280: invalid child");
219262306a36Sopenharmony_ci		RFALSE(!h &&
219362306a36Sopenharmony_ci		       B_FREE_SPACE(bh) !=
219462306a36Sopenharmony_ci		       MAX_CHILD_SIZE(bh) -
219562306a36Sopenharmony_ci		       dc_size(B_N_CHILD(tb->FL[0], child_position)),
219662306a36Sopenharmony_ci		       "PAP-8290: invalid child size of left neighbor");
219762306a36Sopenharmony_ci
219862306a36Sopenharmony_ci		brelse(tb->L[h]);
219962306a36Sopenharmony_ci		tb->L[h] = bh;
220062306a36Sopenharmony_ci	}
220162306a36Sopenharmony_ci
220262306a36Sopenharmony_ci	/* We need right neighbor to balance S[path_offset]. */
220362306a36Sopenharmony_ci	if (tb->rnum[h]) {
220462306a36Sopenharmony_ci		PROC_INFO_INC(sb, need_r_neighbor[h]);
220562306a36Sopenharmony_ci		bh = PATH_OFFSET_PBUFFER(tb->tb_path, path_offset);
220662306a36Sopenharmony_ci
220762306a36Sopenharmony_ci		RFALSE(bh == tb->FR[h] &&
220862306a36Sopenharmony_ci		       PATH_OFFSET_POSITION(tb->tb_path,
220962306a36Sopenharmony_ci					    path_offset) >=
221062306a36Sopenharmony_ci		       B_NR_ITEMS(bh),
221162306a36Sopenharmony_ci		       "PAP-8295: invalid position in the parent");
221262306a36Sopenharmony_ci
221362306a36Sopenharmony_ci		child_position =
221462306a36Sopenharmony_ci		    (bh == tb->FR[h]) ? tb->rkey[h] + 1 : 0;
221562306a36Sopenharmony_ci		son_number = B_N_CHILD_NUM(tb->FR[h], child_position);
221662306a36Sopenharmony_ci		depth = reiserfs_write_unlock_nested(tb->tb_sb);
221762306a36Sopenharmony_ci		bh = sb_bread(sb, son_number);
221862306a36Sopenharmony_ci		reiserfs_write_lock_nested(tb->tb_sb, depth);
221962306a36Sopenharmony_ci		if (!bh)
222062306a36Sopenharmony_ci			return IO_ERROR;
222162306a36Sopenharmony_ci		if (FILESYSTEM_CHANGED_TB(tb)) {
222262306a36Sopenharmony_ci			brelse(bh);
222362306a36Sopenharmony_ci			PROC_INFO_INC(sb, get_neighbors_restart[h]);
222462306a36Sopenharmony_ci			return REPEAT_SEARCH;
222562306a36Sopenharmony_ci		}
222662306a36Sopenharmony_ci		brelse(tb->R[h]);
222762306a36Sopenharmony_ci		tb->R[h] = bh;
222862306a36Sopenharmony_ci
222962306a36Sopenharmony_ci		RFALSE(!h
223062306a36Sopenharmony_ci		       && B_FREE_SPACE(bh) !=
223162306a36Sopenharmony_ci		       MAX_CHILD_SIZE(bh) -
223262306a36Sopenharmony_ci		       dc_size(B_N_CHILD(tb->FR[0], child_position)),
223362306a36Sopenharmony_ci		       "PAP-8300: invalid child size of right neighbor (%d != %d - %d)",
223462306a36Sopenharmony_ci		       B_FREE_SPACE(bh), MAX_CHILD_SIZE(bh),
223562306a36Sopenharmony_ci		       dc_size(B_N_CHILD(tb->FR[0], child_position)));
223662306a36Sopenharmony_ci
223762306a36Sopenharmony_ci	}
223862306a36Sopenharmony_ci	return CARRY_ON;
223962306a36Sopenharmony_ci}
224062306a36Sopenharmony_ci
224162306a36Sopenharmony_cistatic int get_virtual_node_size(struct super_block *sb, struct buffer_head *bh)
224262306a36Sopenharmony_ci{
224362306a36Sopenharmony_ci	int max_num_of_items;
224462306a36Sopenharmony_ci	int max_num_of_entries;
224562306a36Sopenharmony_ci	unsigned long blocksize = sb->s_blocksize;
224662306a36Sopenharmony_ci
224762306a36Sopenharmony_ci#define MIN_NAME_LEN 1
224862306a36Sopenharmony_ci
224962306a36Sopenharmony_ci	max_num_of_items = (blocksize - BLKH_SIZE) / (IH_SIZE + MIN_ITEM_LEN);
225062306a36Sopenharmony_ci	max_num_of_entries = (blocksize - BLKH_SIZE - IH_SIZE) /
225162306a36Sopenharmony_ci	    (DEH_SIZE + MIN_NAME_LEN);
225262306a36Sopenharmony_ci
225362306a36Sopenharmony_ci	return sizeof(struct virtual_node) +
225462306a36Sopenharmony_ci	    max(max_num_of_items * sizeof(struct virtual_item),
225562306a36Sopenharmony_ci		sizeof(struct virtual_item) +
225662306a36Sopenharmony_ci		struct_size_t(struct direntry_uarea, entry_sizes,
225762306a36Sopenharmony_ci			      max_num_of_entries));
225862306a36Sopenharmony_ci}
225962306a36Sopenharmony_ci
226062306a36Sopenharmony_ci/*
226162306a36Sopenharmony_ci * maybe we should fail balancing we are going to perform when kmalloc
226262306a36Sopenharmony_ci * fails several times. But now it will loop until kmalloc gets
226362306a36Sopenharmony_ci * required memory
226462306a36Sopenharmony_ci */
226562306a36Sopenharmony_cistatic int get_mem_for_virtual_node(struct tree_balance *tb)
226662306a36Sopenharmony_ci{
226762306a36Sopenharmony_ci	int check_fs = 0;
226862306a36Sopenharmony_ci	int size;
226962306a36Sopenharmony_ci	char *buf;
227062306a36Sopenharmony_ci
227162306a36Sopenharmony_ci	size = get_virtual_node_size(tb->tb_sb, PATH_PLAST_BUFFER(tb->tb_path));
227262306a36Sopenharmony_ci
227362306a36Sopenharmony_ci	/* we have to allocate more memory for virtual node */
227462306a36Sopenharmony_ci	if (size > tb->vn_buf_size) {
227562306a36Sopenharmony_ci		if (tb->vn_buf) {
227662306a36Sopenharmony_ci			/* free memory allocated before */
227762306a36Sopenharmony_ci			kfree(tb->vn_buf);
227862306a36Sopenharmony_ci			/* this is not needed if kfree is atomic */
227962306a36Sopenharmony_ci			check_fs = 1;
228062306a36Sopenharmony_ci		}
228162306a36Sopenharmony_ci
228262306a36Sopenharmony_ci		/* virtual node requires now more memory */
228362306a36Sopenharmony_ci		tb->vn_buf_size = size;
228462306a36Sopenharmony_ci
228562306a36Sopenharmony_ci		/* get memory for virtual item */
228662306a36Sopenharmony_ci		buf = kmalloc(size, GFP_ATOMIC | __GFP_NOWARN);
228762306a36Sopenharmony_ci		if (!buf) {
228862306a36Sopenharmony_ci			/*
228962306a36Sopenharmony_ci			 * getting memory with GFP_KERNEL priority may involve
229062306a36Sopenharmony_ci			 * balancing now (due to indirect_to_direct conversion
229162306a36Sopenharmony_ci			 * on dcache shrinking). So, release path and collected
229262306a36Sopenharmony_ci			 * resources here
229362306a36Sopenharmony_ci			 */
229462306a36Sopenharmony_ci			free_buffers_in_tb(tb);
229562306a36Sopenharmony_ci			buf = kmalloc(size, GFP_NOFS);
229662306a36Sopenharmony_ci			if (!buf) {
229762306a36Sopenharmony_ci				tb->vn_buf_size = 0;
229862306a36Sopenharmony_ci			}
229962306a36Sopenharmony_ci			tb->vn_buf = buf;
230062306a36Sopenharmony_ci			schedule();
230162306a36Sopenharmony_ci			return REPEAT_SEARCH;
230262306a36Sopenharmony_ci		}
230362306a36Sopenharmony_ci
230462306a36Sopenharmony_ci		tb->vn_buf = buf;
230562306a36Sopenharmony_ci	}
230662306a36Sopenharmony_ci
230762306a36Sopenharmony_ci	if (check_fs && FILESYSTEM_CHANGED_TB(tb))
230862306a36Sopenharmony_ci		return REPEAT_SEARCH;
230962306a36Sopenharmony_ci
231062306a36Sopenharmony_ci	return CARRY_ON;
231162306a36Sopenharmony_ci}
231262306a36Sopenharmony_ci
231362306a36Sopenharmony_ci#ifdef CONFIG_REISERFS_CHECK
231462306a36Sopenharmony_cistatic void tb_buffer_sanity_check(struct super_block *sb,
231562306a36Sopenharmony_ci				   struct buffer_head *bh,
231662306a36Sopenharmony_ci				   const char *descr, int level)
231762306a36Sopenharmony_ci{
231862306a36Sopenharmony_ci	if (bh) {
231962306a36Sopenharmony_ci		if (atomic_read(&(bh->b_count)) <= 0)
232062306a36Sopenharmony_ci
232162306a36Sopenharmony_ci			reiserfs_panic(sb, "jmacd-1", "negative or zero "
232262306a36Sopenharmony_ci				       "reference counter for buffer %s[%d] "
232362306a36Sopenharmony_ci				       "(%b)", descr, level, bh);
232462306a36Sopenharmony_ci
232562306a36Sopenharmony_ci		if (!buffer_uptodate(bh))
232662306a36Sopenharmony_ci			reiserfs_panic(sb, "jmacd-2", "buffer is not up "
232762306a36Sopenharmony_ci				       "to date %s[%d] (%b)",
232862306a36Sopenharmony_ci				       descr, level, bh);
232962306a36Sopenharmony_ci
233062306a36Sopenharmony_ci		if (!B_IS_IN_TREE(bh))
233162306a36Sopenharmony_ci			reiserfs_panic(sb, "jmacd-3", "buffer is not "
233262306a36Sopenharmony_ci				       "in tree %s[%d] (%b)",
233362306a36Sopenharmony_ci				       descr, level, bh);
233462306a36Sopenharmony_ci
233562306a36Sopenharmony_ci		if (bh->b_bdev != sb->s_bdev)
233662306a36Sopenharmony_ci			reiserfs_panic(sb, "jmacd-4", "buffer has wrong "
233762306a36Sopenharmony_ci				       "device %s[%d] (%b)",
233862306a36Sopenharmony_ci				       descr, level, bh);
233962306a36Sopenharmony_ci
234062306a36Sopenharmony_ci		if (bh->b_size != sb->s_blocksize)
234162306a36Sopenharmony_ci			reiserfs_panic(sb, "jmacd-5", "buffer has wrong "
234262306a36Sopenharmony_ci				       "blocksize %s[%d] (%b)",
234362306a36Sopenharmony_ci				       descr, level, bh);
234462306a36Sopenharmony_ci
234562306a36Sopenharmony_ci		if (bh->b_blocknr > SB_BLOCK_COUNT(sb))
234662306a36Sopenharmony_ci			reiserfs_panic(sb, "jmacd-6", "buffer block "
234762306a36Sopenharmony_ci				       "number too high %s[%d] (%b)",
234862306a36Sopenharmony_ci				       descr, level, bh);
234962306a36Sopenharmony_ci	}
235062306a36Sopenharmony_ci}
235162306a36Sopenharmony_ci#else
235262306a36Sopenharmony_cistatic void tb_buffer_sanity_check(struct super_block *sb,
235362306a36Sopenharmony_ci				   struct buffer_head *bh,
235462306a36Sopenharmony_ci				   const char *descr, int level)
235562306a36Sopenharmony_ci{;
235662306a36Sopenharmony_ci}
235762306a36Sopenharmony_ci#endif
235862306a36Sopenharmony_ci
235962306a36Sopenharmony_cistatic int clear_all_dirty_bits(struct super_block *s, struct buffer_head *bh)
236062306a36Sopenharmony_ci{
236162306a36Sopenharmony_ci	return reiserfs_prepare_for_journal(s, bh, 0);
236262306a36Sopenharmony_ci}
236362306a36Sopenharmony_ci
236462306a36Sopenharmony_cistatic int wait_tb_buffers_until_unlocked(struct tree_balance *tb)
236562306a36Sopenharmony_ci{
236662306a36Sopenharmony_ci	struct buffer_head *locked;
236762306a36Sopenharmony_ci#ifdef CONFIG_REISERFS_CHECK
236862306a36Sopenharmony_ci	int repeat_counter = 0;
236962306a36Sopenharmony_ci#endif
237062306a36Sopenharmony_ci	int i;
237162306a36Sopenharmony_ci
237262306a36Sopenharmony_ci	do {
237362306a36Sopenharmony_ci
237462306a36Sopenharmony_ci		locked = NULL;
237562306a36Sopenharmony_ci
237662306a36Sopenharmony_ci		for (i = tb->tb_path->path_length;
237762306a36Sopenharmony_ci		     !locked && i > ILLEGAL_PATH_ELEMENT_OFFSET; i--) {
237862306a36Sopenharmony_ci			if (PATH_OFFSET_PBUFFER(tb->tb_path, i)) {
237962306a36Sopenharmony_ci				/*
238062306a36Sopenharmony_ci				 * if I understand correctly, we can only
238162306a36Sopenharmony_ci				 * be sure the last buffer in the path is
238262306a36Sopenharmony_ci				 * in the tree --clm
238362306a36Sopenharmony_ci				 */
238462306a36Sopenharmony_ci#ifdef CONFIG_REISERFS_CHECK
238562306a36Sopenharmony_ci				if (PATH_PLAST_BUFFER(tb->tb_path) ==
238662306a36Sopenharmony_ci				    PATH_OFFSET_PBUFFER(tb->tb_path, i))
238762306a36Sopenharmony_ci					tb_buffer_sanity_check(tb->tb_sb,
238862306a36Sopenharmony_ci							       PATH_OFFSET_PBUFFER
238962306a36Sopenharmony_ci							       (tb->tb_path,
239062306a36Sopenharmony_ci								i), "S",
239162306a36Sopenharmony_ci							       tb->tb_path->
239262306a36Sopenharmony_ci							       path_length - i);
239362306a36Sopenharmony_ci#endif
239462306a36Sopenharmony_ci				if (!clear_all_dirty_bits(tb->tb_sb,
239562306a36Sopenharmony_ci							  PATH_OFFSET_PBUFFER
239662306a36Sopenharmony_ci							  (tb->tb_path,
239762306a36Sopenharmony_ci							   i))) {
239862306a36Sopenharmony_ci					locked =
239962306a36Sopenharmony_ci					    PATH_OFFSET_PBUFFER(tb->tb_path,
240062306a36Sopenharmony_ci								i);
240162306a36Sopenharmony_ci				}
240262306a36Sopenharmony_ci			}
240362306a36Sopenharmony_ci		}
240462306a36Sopenharmony_ci
240562306a36Sopenharmony_ci		for (i = 0; !locked && i < MAX_HEIGHT && tb->insert_size[i];
240662306a36Sopenharmony_ci		     i++) {
240762306a36Sopenharmony_ci
240862306a36Sopenharmony_ci			if (tb->lnum[i]) {
240962306a36Sopenharmony_ci
241062306a36Sopenharmony_ci				if (tb->L[i]) {
241162306a36Sopenharmony_ci					tb_buffer_sanity_check(tb->tb_sb,
241262306a36Sopenharmony_ci							       tb->L[i],
241362306a36Sopenharmony_ci							       "L", i);
241462306a36Sopenharmony_ci					if (!clear_all_dirty_bits
241562306a36Sopenharmony_ci					    (tb->tb_sb, tb->L[i]))
241662306a36Sopenharmony_ci						locked = tb->L[i];
241762306a36Sopenharmony_ci				}
241862306a36Sopenharmony_ci
241962306a36Sopenharmony_ci				if (!locked && tb->FL[i]) {
242062306a36Sopenharmony_ci					tb_buffer_sanity_check(tb->tb_sb,
242162306a36Sopenharmony_ci							       tb->FL[i],
242262306a36Sopenharmony_ci							       "FL", i);
242362306a36Sopenharmony_ci					if (!clear_all_dirty_bits
242462306a36Sopenharmony_ci					    (tb->tb_sb, tb->FL[i]))
242562306a36Sopenharmony_ci						locked = tb->FL[i];
242662306a36Sopenharmony_ci				}
242762306a36Sopenharmony_ci
242862306a36Sopenharmony_ci				if (!locked && tb->CFL[i]) {
242962306a36Sopenharmony_ci					tb_buffer_sanity_check(tb->tb_sb,
243062306a36Sopenharmony_ci							       tb->CFL[i],
243162306a36Sopenharmony_ci							       "CFL", i);
243262306a36Sopenharmony_ci					if (!clear_all_dirty_bits
243362306a36Sopenharmony_ci					    (tb->tb_sb, tb->CFL[i]))
243462306a36Sopenharmony_ci						locked = tb->CFL[i];
243562306a36Sopenharmony_ci				}
243662306a36Sopenharmony_ci
243762306a36Sopenharmony_ci			}
243862306a36Sopenharmony_ci
243962306a36Sopenharmony_ci			if (!locked && (tb->rnum[i])) {
244062306a36Sopenharmony_ci
244162306a36Sopenharmony_ci				if (tb->R[i]) {
244262306a36Sopenharmony_ci					tb_buffer_sanity_check(tb->tb_sb,
244362306a36Sopenharmony_ci							       tb->R[i],
244462306a36Sopenharmony_ci							       "R", i);
244562306a36Sopenharmony_ci					if (!clear_all_dirty_bits
244662306a36Sopenharmony_ci					    (tb->tb_sb, tb->R[i]))
244762306a36Sopenharmony_ci						locked = tb->R[i];
244862306a36Sopenharmony_ci				}
244962306a36Sopenharmony_ci
245062306a36Sopenharmony_ci				if (!locked && tb->FR[i]) {
245162306a36Sopenharmony_ci					tb_buffer_sanity_check(tb->tb_sb,
245262306a36Sopenharmony_ci							       tb->FR[i],
245362306a36Sopenharmony_ci							       "FR", i);
245462306a36Sopenharmony_ci					if (!clear_all_dirty_bits
245562306a36Sopenharmony_ci					    (tb->tb_sb, tb->FR[i]))
245662306a36Sopenharmony_ci						locked = tb->FR[i];
245762306a36Sopenharmony_ci				}
245862306a36Sopenharmony_ci
245962306a36Sopenharmony_ci				if (!locked && tb->CFR[i]) {
246062306a36Sopenharmony_ci					tb_buffer_sanity_check(tb->tb_sb,
246162306a36Sopenharmony_ci							       tb->CFR[i],
246262306a36Sopenharmony_ci							       "CFR", i);
246362306a36Sopenharmony_ci					if (!clear_all_dirty_bits
246462306a36Sopenharmony_ci					    (tb->tb_sb, tb->CFR[i]))
246562306a36Sopenharmony_ci						locked = tb->CFR[i];
246662306a36Sopenharmony_ci				}
246762306a36Sopenharmony_ci			}
246862306a36Sopenharmony_ci		}
246962306a36Sopenharmony_ci
247062306a36Sopenharmony_ci		/*
247162306a36Sopenharmony_ci		 * as far as I can tell, this is not required.  The FEB list
247262306a36Sopenharmony_ci		 * seems to be full of newly allocated nodes, which will
247362306a36Sopenharmony_ci		 * never be locked, dirty, or anything else.
247462306a36Sopenharmony_ci		 * To be safe, I'm putting in the checks and waits in.
247562306a36Sopenharmony_ci		 * For the moment, they are needed to keep the code in
247662306a36Sopenharmony_ci		 * journal.c from complaining about the buffer.
247762306a36Sopenharmony_ci		 * That code is inside CONFIG_REISERFS_CHECK as well.  --clm
247862306a36Sopenharmony_ci		 */
247962306a36Sopenharmony_ci		for (i = 0; !locked && i < MAX_FEB_SIZE; i++) {
248062306a36Sopenharmony_ci			if (tb->FEB[i]) {
248162306a36Sopenharmony_ci				if (!clear_all_dirty_bits
248262306a36Sopenharmony_ci				    (tb->tb_sb, tb->FEB[i]))
248362306a36Sopenharmony_ci					locked = tb->FEB[i];
248462306a36Sopenharmony_ci			}
248562306a36Sopenharmony_ci		}
248662306a36Sopenharmony_ci
248762306a36Sopenharmony_ci		if (locked) {
248862306a36Sopenharmony_ci			int depth;
248962306a36Sopenharmony_ci#ifdef CONFIG_REISERFS_CHECK
249062306a36Sopenharmony_ci			repeat_counter++;
249162306a36Sopenharmony_ci			if ((repeat_counter % 10000) == 0) {
249262306a36Sopenharmony_ci				reiserfs_warning(tb->tb_sb, "reiserfs-8200",
249362306a36Sopenharmony_ci						 "too many iterations waiting "
249462306a36Sopenharmony_ci						 "for buffer to unlock "
249562306a36Sopenharmony_ci						 "(%b)", locked);
249662306a36Sopenharmony_ci
249762306a36Sopenharmony_ci				/* Don't loop forever.  Try to recover from possible error. */
249862306a36Sopenharmony_ci
249962306a36Sopenharmony_ci				return (FILESYSTEM_CHANGED_TB(tb)) ?
250062306a36Sopenharmony_ci				    REPEAT_SEARCH : CARRY_ON;
250162306a36Sopenharmony_ci			}
250262306a36Sopenharmony_ci#endif
250362306a36Sopenharmony_ci			depth = reiserfs_write_unlock_nested(tb->tb_sb);
250462306a36Sopenharmony_ci			__wait_on_buffer(locked);
250562306a36Sopenharmony_ci			reiserfs_write_lock_nested(tb->tb_sb, depth);
250662306a36Sopenharmony_ci			if (FILESYSTEM_CHANGED_TB(tb))
250762306a36Sopenharmony_ci				return REPEAT_SEARCH;
250862306a36Sopenharmony_ci		}
250962306a36Sopenharmony_ci
251062306a36Sopenharmony_ci	} while (locked);
251162306a36Sopenharmony_ci
251262306a36Sopenharmony_ci	return CARRY_ON;
251362306a36Sopenharmony_ci}
251462306a36Sopenharmony_ci
251562306a36Sopenharmony_ci/*
251662306a36Sopenharmony_ci * Prepare for balancing, that is
251762306a36Sopenharmony_ci *	get all necessary parents, and neighbors;
251862306a36Sopenharmony_ci *	analyze what and where should be moved;
251962306a36Sopenharmony_ci *	get sufficient number of new nodes;
252062306a36Sopenharmony_ci * Balancing will start only after all resources will be collected at a time.
252162306a36Sopenharmony_ci *
252262306a36Sopenharmony_ci * When ported to SMP kernels, only at the last moment after all needed nodes
252362306a36Sopenharmony_ci * are collected in cache, will the resources be locked using the usual
252462306a36Sopenharmony_ci * textbook ordered lock acquisition algorithms.  Note that ensuring that
252562306a36Sopenharmony_ci * this code neither write locks what it does not need to write lock nor locks
252662306a36Sopenharmony_ci * out of order will be a pain in the butt that could have been avoided.
252762306a36Sopenharmony_ci * Grumble grumble. -Hans
252862306a36Sopenharmony_ci *
252962306a36Sopenharmony_ci * fix is meant in the sense of render unchanging
253062306a36Sopenharmony_ci *
253162306a36Sopenharmony_ci * Latency might be improved by first gathering a list of what buffers
253262306a36Sopenharmony_ci * are needed and then getting as many of them in parallel as possible? -Hans
253362306a36Sopenharmony_ci *
253462306a36Sopenharmony_ci * Parameters:
253562306a36Sopenharmony_ci *	op_mode	i - insert, d - delete, c - cut (truncate), p - paste (append)
253662306a36Sopenharmony_ci *	tb	tree_balance structure;
253762306a36Sopenharmony_ci *	inum	item number in S[h];
253862306a36Sopenharmony_ci *      pos_in_item - comment this if you can
253962306a36Sopenharmony_ci *      ins_ih	item head of item being inserted
254062306a36Sopenharmony_ci *	data	inserted item or data to be pasted
254162306a36Sopenharmony_ci * Returns:	1 - schedule occurred while the function worked;
254262306a36Sopenharmony_ci *	        0 - schedule didn't occur while the function worked;
254362306a36Sopenharmony_ci *             -1 - if no_disk_space
254462306a36Sopenharmony_ci */
254562306a36Sopenharmony_ci
254662306a36Sopenharmony_ciint fix_nodes(int op_mode, struct tree_balance *tb,
254762306a36Sopenharmony_ci	      struct item_head *ins_ih, const void *data)
254862306a36Sopenharmony_ci{
254962306a36Sopenharmony_ci	int ret, h, item_num = PATH_LAST_POSITION(tb->tb_path);
255062306a36Sopenharmony_ci	int pos_in_item;
255162306a36Sopenharmony_ci
255262306a36Sopenharmony_ci	/*
255362306a36Sopenharmony_ci	 * we set wait_tb_buffers_run when we have to restore any dirty
255462306a36Sopenharmony_ci	 * bits cleared during wait_tb_buffers_run
255562306a36Sopenharmony_ci	 */
255662306a36Sopenharmony_ci	int wait_tb_buffers_run = 0;
255762306a36Sopenharmony_ci	struct buffer_head *tbS0 = PATH_PLAST_BUFFER(tb->tb_path);
255862306a36Sopenharmony_ci
255962306a36Sopenharmony_ci	++REISERFS_SB(tb->tb_sb)->s_fix_nodes;
256062306a36Sopenharmony_ci
256162306a36Sopenharmony_ci	pos_in_item = tb->tb_path->pos_in_item;
256262306a36Sopenharmony_ci
256362306a36Sopenharmony_ci	tb->fs_gen = get_generation(tb->tb_sb);
256462306a36Sopenharmony_ci
256562306a36Sopenharmony_ci	/*
256662306a36Sopenharmony_ci	 * we prepare and log the super here so it will already be in the
256762306a36Sopenharmony_ci	 * transaction when do_balance needs to change it.
256862306a36Sopenharmony_ci	 * This way do_balance won't have to schedule when trying to prepare
256962306a36Sopenharmony_ci	 * the super for logging
257062306a36Sopenharmony_ci	 */
257162306a36Sopenharmony_ci	reiserfs_prepare_for_journal(tb->tb_sb,
257262306a36Sopenharmony_ci				     SB_BUFFER_WITH_SB(tb->tb_sb), 1);
257362306a36Sopenharmony_ci	journal_mark_dirty(tb->transaction_handle,
257462306a36Sopenharmony_ci			   SB_BUFFER_WITH_SB(tb->tb_sb));
257562306a36Sopenharmony_ci	if (FILESYSTEM_CHANGED_TB(tb))
257662306a36Sopenharmony_ci		return REPEAT_SEARCH;
257762306a36Sopenharmony_ci
257862306a36Sopenharmony_ci	/* if it possible in indirect_to_direct conversion */
257962306a36Sopenharmony_ci	if (buffer_locked(tbS0)) {
258062306a36Sopenharmony_ci		int depth = reiserfs_write_unlock_nested(tb->tb_sb);
258162306a36Sopenharmony_ci		__wait_on_buffer(tbS0);
258262306a36Sopenharmony_ci		reiserfs_write_lock_nested(tb->tb_sb, depth);
258362306a36Sopenharmony_ci		if (FILESYSTEM_CHANGED_TB(tb))
258462306a36Sopenharmony_ci			return REPEAT_SEARCH;
258562306a36Sopenharmony_ci	}
258662306a36Sopenharmony_ci#ifdef CONFIG_REISERFS_CHECK
258762306a36Sopenharmony_ci	if (REISERFS_SB(tb->tb_sb)->cur_tb) {
258862306a36Sopenharmony_ci		print_cur_tb("fix_nodes");
258962306a36Sopenharmony_ci		reiserfs_panic(tb->tb_sb, "PAP-8305",
259062306a36Sopenharmony_ci			       "there is pending do_balance");
259162306a36Sopenharmony_ci	}
259262306a36Sopenharmony_ci
259362306a36Sopenharmony_ci	if (!buffer_uptodate(tbS0) || !B_IS_IN_TREE(tbS0))
259462306a36Sopenharmony_ci		reiserfs_panic(tb->tb_sb, "PAP-8320", "S[0] (%b %z) is "
259562306a36Sopenharmony_ci			       "not uptodate at the beginning of fix_nodes "
259662306a36Sopenharmony_ci			       "or not in tree (mode %c)",
259762306a36Sopenharmony_ci			       tbS0, tbS0, op_mode);
259862306a36Sopenharmony_ci
259962306a36Sopenharmony_ci	/* Check parameters. */
260062306a36Sopenharmony_ci	switch (op_mode) {
260162306a36Sopenharmony_ci	case M_INSERT:
260262306a36Sopenharmony_ci		if (item_num <= 0 || item_num > B_NR_ITEMS(tbS0))
260362306a36Sopenharmony_ci			reiserfs_panic(tb->tb_sb, "PAP-8330", "Incorrect "
260462306a36Sopenharmony_ci				       "item number %d (in S0 - %d) in case "
260562306a36Sopenharmony_ci				       "of insert", item_num,
260662306a36Sopenharmony_ci				       B_NR_ITEMS(tbS0));
260762306a36Sopenharmony_ci		break;
260862306a36Sopenharmony_ci	case M_PASTE:
260962306a36Sopenharmony_ci	case M_DELETE:
261062306a36Sopenharmony_ci	case M_CUT:
261162306a36Sopenharmony_ci		if (item_num < 0 || item_num >= B_NR_ITEMS(tbS0)) {
261262306a36Sopenharmony_ci			print_block(tbS0, 0, -1, -1);
261362306a36Sopenharmony_ci			reiserfs_panic(tb->tb_sb, "PAP-8335", "Incorrect "
261462306a36Sopenharmony_ci				       "item number(%d); mode = %c "
261562306a36Sopenharmony_ci				       "insert_size = %d",
261662306a36Sopenharmony_ci				       item_num, op_mode,
261762306a36Sopenharmony_ci				       tb->insert_size[0]);
261862306a36Sopenharmony_ci		}
261962306a36Sopenharmony_ci		break;
262062306a36Sopenharmony_ci	default:
262162306a36Sopenharmony_ci		reiserfs_panic(tb->tb_sb, "PAP-8340", "Incorrect mode "
262262306a36Sopenharmony_ci			       "of operation");
262362306a36Sopenharmony_ci	}
262462306a36Sopenharmony_ci#endif
262562306a36Sopenharmony_ci
262662306a36Sopenharmony_ci	if (get_mem_for_virtual_node(tb) == REPEAT_SEARCH)
262762306a36Sopenharmony_ci		/* FIXME: maybe -ENOMEM when tb->vn_buf == 0? Now just repeat */
262862306a36Sopenharmony_ci		return REPEAT_SEARCH;
262962306a36Sopenharmony_ci
263062306a36Sopenharmony_ci	/* Starting from the leaf level; for all levels h of the tree. */
263162306a36Sopenharmony_ci	for (h = 0; h < MAX_HEIGHT && tb->insert_size[h]; h++) {
263262306a36Sopenharmony_ci		ret = get_direct_parent(tb, h);
263362306a36Sopenharmony_ci		if (ret != CARRY_ON)
263462306a36Sopenharmony_ci			goto repeat;
263562306a36Sopenharmony_ci
263662306a36Sopenharmony_ci		ret = check_balance(op_mode, tb, h, item_num,
263762306a36Sopenharmony_ci				    pos_in_item, ins_ih, data);
263862306a36Sopenharmony_ci		if (ret != CARRY_ON) {
263962306a36Sopenharmony_ci			if (ret == NO_BALANCING_NEEDED) {
264062306a36Sopenharmony_ci				/* No balancing for higher levels needed. */
264162306a36Sopenharmony_ci				ret = get_neighbors(tb, h);
264262306a36Sopenharmony_ci				if (ret != CARRY_ON)
264362306a36Sopenharmony_ci					goto repeat;
264462306a36Sopenharmony_ci				if (h != MAX_HEIGHT - 1)
264562306a36Sopenharmony_ci					tb->insert_size[h + 1] = 0;
264662306a36Sopenharmony_ci				/*
264762306a36Sopenharmony_ci				 * ok, analysis and resource gathering
264862306a36Sopenharmony_ci				 * are complete
264962306a36Sopenharmony_ci				 */
265062306a36Sopenharmony_ci				break;
265162306a36Sopenharmony_ci			}
265262306a36Sopenharmony_ci			goto repeat;
265362306a36Sopenharmony_ci		}
265462306a36Sopenharmony_ci
265562306a36Sopenharmony_ci		ret = get_neighbors(tb, h);
265662306a36Sopenharmony_ci		if (ret != CARRY_ON)
265762306a36Sopenharmony_ci			goto repeat;
265862306a36Sopenharmony_ci
265962306a36Sopenharmony_ci		/*
266062306a36Sopenharmony_ci		 * No disk space, or schedule occurred and analysis may be
266162306a36Sopenharmony_ci		 * invalid and needs to be redone.
266262306a36Sopenharmony_ci		 */
266362306a36Sopenharmony_ci		ret = get_empty_nodes(tb, h);
266462306a36Sopenharmony_ci		if (ret != CARRY_ON)
266562306a36Sopenharmony_ci			goto repeat;
266662306a36Sopenharmony_ci
266762306a36Sopenharmony_ci		/*
266862306a36Sopenharmony_ci		 * We have a positive insert size but no nodes exist on this
266962306a36Sopenharmony_ci		 * level, this means that we are creating a new root.
267062306a36Sopenharmony_ci		 */
267162306a36Sopenharmony_ci		if (!PATH_H_PBUFFER(tb->tb_path, h)) {
267262306a36Sopenharmony_ci
267362306a36Sopenharmony_ci			RFALSE(tb->blknum[h] != 1,
267462306a36Sopenharmony_ci			       "PAP-8350: creating new empty root");
267562306a36Sopenharmony_ci
267662306a36Sopenharmony_ci			if (h < MAX_HEIGHT - 1)
267762306a36Sopenharmony_ci				tb->insert_size[h + 1] = 0;
267862306a36Sopenharmony_ci		} else if (!PATH_H_PBUFFER(tb->tb_path, h + 1)) {
267962306a36Sopenharmony_ci			/*
268062306a36Sopenharmony_ci			 * The tree needs to be grown, so this node S[h]
268162306a36Sopenharmony_ci			 * which is the root node is split into two nodes,
268262306a36Sopenharmony_ci			 * and a new node (S[h+1]) will be created to
268362306a36Sopenharmony_ci			 * become the root node.
268462306a36Sopenharmony_ci			 */
268562306a36Sopenharmony_ci			if (tb->blknum[h] > 1) {
268662306a36Sopenharmony_ci
268762306a36Sopenharmony_ci				RFALSE(h == MAX_HEIGHT - 1,
268862306a36Sopenharmony_ci				       "PAP-8355: attempt to create too high of a tree");
268962306a36Sopenharmony_ci
269062306a36Sopenharmony_ci				tb->insert_size[h + 1] =
269162306a36Sopenharmony_ci				    (DC_SIZE +
269262306a36Sopenharmony_ci				     KEY_SIZE) * (tb->blknum[h] - 1) +
269362306a36Sopenharmony_ci				    DC_SIZE;
269462306a36Sopenharmony_ci			} else if (h < MAX_HEIGHT - 1)
269562306a36Sopenharmony_ci				tb->insert_size[h + 1] = 0;
269662306a36Sopenharmony_ci		} else
269762306a36Sopenharmony_ci			tb->insert_size[h + 1] =
269862306a36Sopenharmony_ci			    (DC_SIZE + KEY_SIZE) * (tb->blknum[h] - 1);
269962306a36Sopenharmony_ci	}
270062306a36Sopenharmony_ci
270162306a36Sopenharmony_ci	ret = wait_tb_buffers_until_unlocked(tb);
270262306a36Sopenharmony_ci	if (ret == CARRY_ON) {
270362306a36Sopenharmony_ci		if (FILESYSTEM_CHANGED_TB(tb)) {
270462306a36Sopenharmony_ci			wait_tb_buffers_run = 1;
270562306a36Sopenharmony_ci			ret = REPEAT_SEARCH;
270662306a36Sopenharmony_ci			goto repeat;
270762306a36Sopenharmony_ci		} else {
270862306a36Sopenharmony_ci			return CARRY_ON;
270962306a36Sopenharmony_ci		}
271062306a36Sopenharmony_ci	} else {
271162306a36Sopenharmony_ci		wait_tb_buffers_run = 1;
271262306a36Sopenharmony_ci		goto repeat;
271362306a36Sopenharmony_ci	}
271462306a36Sopenharmony_ci
271562306a36Sopenharmony_cirepeat:
271662306a36Sopenharmony_ci	/*
271762306a36Sopenharmony_ci	 * fix_nodes was unable to perform its calculation due to
271862306a36Sopenharmony_ci	 * filesystem got changed under us, lack of free disk space or i/o
271962306a36Sopenharmony_ci	 * failure. If the first is the case - the search will be
272062306a36Sopenharmony_ci	 * repeated. For now - free all resources acquired so far except
272162306a36Sopenharmony_ci	 * for the new allocated nodes
272262306a36Sopenharmony_ci	 */
272362306a36Sopenharmony_ci	{
272462306a36Sopenharmony_ci		int i;
272562306a36Sopenharmony_ci
272662306a36Sopenharmony_ci		/* Release path buffers. */
272762306a36Sopenharmony_ci		if (wait_tb_buffers_run) {
272862306a36Sopenharmony_ci			pathrelse_and_restore(tb->tb_sb, tb->tb_path);
272962306a36Sopenharmony_ci		} else {
273062306a36Sopenharmony_ci			pathrelse(tb->tb_path);
273162306a36Sopenharmony_ci		}
273262306a36Sopenharmony_ci		/* brelse all resources collected for balancing */
273362306a36Sopenharmony_ci		for (i = 0; i < MAX_HEIGHT; i++) {
273462306a36Sopenharmony_ci			if (wait_tb_buffers_run) {
273562306a36Sopenharmony_ci				reiserfs_restore_prepared_buffer(tb->tb_sb,
273662306a36Sopenharmony_ci								 tb->L[i]);
273762306a36Sopenharmony_ci				reiserfs_restore_prepared_buffer(tb->tb_sb,
273862306a36Sopenharmony_ci								 tb->R[i]);
273962306a36Sopenharmony_ci				reiserfs_restore_prepared_buffer(tb->tb_sb,
274062306a36Sopenharmony_ci								 tb->FL[i]);
274162306a36Sopenharmony_ci				reiserfs_restore_prepared_buffer(tb->tb_sb,
274262306a36Sopenharmony_ci								 tb->FR[i]);
274362306a36Sopenharmony_ci				reiserfs_restore_prepared_buffer(tb->tb_sb,
274462306a36Sopenharmony_ci								 tb->
274562306a36Sopenharmony_ci								 CFL[i]);
274662306a36Sopenharmony_ci				reiserfs_restore_prepared_buffer(tb->tb_sb,
274762306a36Sopenharmony_ci								 tb->
274862306a36Sopenharmony_ci								 CFR[i]);
274962306a36Sopenharmony_ci			}
275062306a36Sopenharmony_ci
275162306a36Sopenharmony_ci			brelse(tb->L[i]);
275262306a36Sopenharmony_ci			brelse(tb->R[i]);
275362306a36Sopenharmony_ci			brelse(tb->FL[i]);
275462306a36Sopenharmony_ci			brelse(tb->FR[i]);
275562306a36Sopenharmony_ci			brelse(tb->CFL[i]);
275662306a36Sopenharmony_ci			brelse(tb->CFR[i]);
275762306a36Sopenharmony_ci
275862306a36Sopenharmony_ci			tb->L[i] = NULL;
275962306a36Sopenharmony_ci			tb->R[i] = NULL;
276062306a36Sopenharmony_ci			tb->FL[i] = NULL;
276162306a36Sopenharmony_ci			tb->FR[i] = NULL;
276262306a36Sopenharmony_ci			tb->CFL[i] = NULL;
276362306a36Sopenharmony_ci			tb->CFR[i] = NULL;
276462306a36Sopenharmony_ci		}
276562306a36Sopenharmony_ci
276662306a36Sopenharmony_ci		if (wait_tb_buffers_run) {
276762306a36Sopenharmony_ci			for (i = 0; i < MAX_FEB_SIZE; i++) {
276862306a36Sopenharmony_ci				if (tb->FEB[i])
276962306a36Sopenharmony_ci					reiserfs_restore_prepared_buffer
277062306a36Sopenharmony_ci					    (tb->tb_sb, tb->FEB[i]);
277162306a36Sopenharmony_ci			}
277262306a36Sopenharmony_ci		}
277362306a36Sopenharmony_ci		return ret;
277462306a36Sopenharmony_ci	}
277562306a36Sopenharmony_ci
277662306a36Sopenharmony_ci}
277762306a36Sopenharmony_ci
277862306a36Sopenharmony_civoid unfix_nodes(struct tree_balance *tb)
277962306a36Sopenharmony_ci{
278062306a36Sopenharmony_ci	int i;
278162306a36Sopenharmony_ci
278262306a36Sopenharmony_ci	/* Release path buffers. */
278362306a36Sopenharmony_ci	pathrelse_and_restore(tb->tb_sb, tb->tb_path);
278462306a36Sopenharmony_ci
278562306a36Sopenharmony_ci	/* brelse all resources collected for balancing */
278662306a36Sopenharmony_ci	for (i = 0; i < MAX_HEIGHT; i++) {
278762306a36Sopenharmony_ci		reiserfs_restore_prepared_buffer(tb->tb_sb, tb->L[i]);
278862306a36Sopenharmony_ci		reiserfs_restore_prepared_buffer(tb->tb_sb, tb->R[i]);
278962306a36Sopenharmony_ci		reiserfs_restore_prepared_buffer(tb->tb_sb, tb->FL[i]);
279062306a36Sopenharmony_ci		reiserfs_restore_prepared_buffer(tb->tb_sb, tb->FR[i]);
279162306a36Sopenharmony_ci		reiserfs_restore_prepared_buffer(tb->tb_sb, tb->CFL[i]);
279262306a36Sopenharmony_ci		reiserfs_restore_prepared_buffer(tb->tb_sb, tb->CFR[i]);
279362306a36Sopenharmony_ci
279462306a36Sopenharmony_ci		brelse(tb->L[i]);
279562306a36Sopenharmony_ci		brelse(tb->R[i]);
279662306a36Sopenharmony_ci		brelse(tb->FL[i]);
279762306a36Sopenharmony_ci		brelse(tb->FR[i]);
279862306a36Sopenharmony_ci		brelse(tb->CFL[i]);
279962306a36Sopenharmony_ci		brelse(tb->CFR[i]);
280062306a36Sopenharmony_ci	}
280162306a36Sopenharmony_ci
280262306a36Sopenharmony_ci	/* deal with list of allocated (used and unused) nodes */
280362306a36Sopenharmony_ci	for (i = 0; i < MAX_FEB_SIZE; i++) {
280462306a36Sopenharmony_ci		if (tb->FEB[i]) {
280562306a36Sopenharmony_ci			b_blocknr_t blocknr = tb->FEB[i]->b_blocknr;
280662306a36Sopenharmony_ci			/*
280762306a36Sopenharmony_ci			 * de-allocated block which was not used by
280862306a36Sopenharmony_ci			 * balancing and bforget about buffer for it
280962306a36Sopenharmony_ci			 */
281062306a36Sopenharmony_ci			brelse(tb->FEB[i]);
281162306a36Sopenharmony_ci			reiserfs_free_block(tb->transaction_handle, NULL,
281262306a36Sopenharmony_ci					    blocknr, 0);
281362306a36Sopenharmony_ci		}
281462306a36Sopenharmony_ci		if (tb->used[i]) {
281562306a36Sopenharmony_ci			/* release used as new nodes including a new root */
281662306a36Sopenharmony_ci			brelse(tb->used[i]);
281762306a36Sopenharmony_ci		}
281862306a36Sopenharmony_ci	}
281962306a36Sopenharmony_ci
282062306a36Sopenharmony_ci	kfree(tb->vn_buf);
282162306a36Sopenharmony_ci
282262306a36Sopenharmony_ci}
2823