/*
* Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
*/
#include <linux/config.h>
#include <asm/uaccess.h>
#include <linux/string.h>
#include <linux/time.h>
#include <linux/reiserfs_fs.h>
#include <linux/buffer_head.h>
/* this is one and only function that is used outside (do_balance.c) */
int balance_internal (
struct tree_balance * ,
int,
int,
struct item_head * ,
struct buffer_head **
);
/* modes of internal_shift_left, internal_shift_right and internal_insert_childs */
#define INTERNAL_SHIFT_FROM_S_TO_L 0
#define INTERNAL_SHIFT_FROM_R_TO_S 1
#define INTERNAL_SHIFT_FROM_L_TO_S 2
#define INTERNAL_SHIFT_FROM_S_TO_R 3
#define INTERNAL_INSERT_TO_S 4
#define INTERNAL_INSERT_TO_L 5
#define INTERNAL_INSERT_TO_R 6
static void internal_define_dest_src_infos (
int shift_mode,
struct tree_balance * tb,
int h,
struct buffer_info * dest_bi,
struct buffer_info * src_bi,
int * d_key,
struct buffer_head ** cf
)
{
memset (dest_bi, 0, sizeof (struct buffer_info));
memset (src_bi, 0, sizeof (struct buffer_info));
/* define dest, src, dest parent, dest position */
switch (shift_mode) {
case INTERNAL_SHIFT_FROM_S_TO_L: /* used in internal_shift_left */
src_bi->tb = tb;
src_bi->bi_bh = PATH_H_PBUFFER (tb->tb_path, h);
src_bi->bi_parent = PATH_H_PPARENT (tb->tb_path, h);
src_bi->bi_position = PATH_H_POSITION (tb->tb_path, h + 1);
dest_bi->tb = tb;
dest_bi->bi_bh = tb->L[h];
dest_bi->bi_parent = tb->FL[h];
dest_bi->bi_position = get_left_neighbor_position (tb, h);
*d_key = tb->lkey[h];
*cf = tb->CFL[h];
break;
case INTERNAL_SHIFT_FROM_L_TO_S:
src_bi->tb = tb;
src_bi->bi_bh = tb->L[h];
src_bi->bi_parent = tb->FL[h];
src_bi->bi_position = get_left_neighbor_position (tb, h);
dest_bi->tb = tb;
dest_bi->bi_bh = PATH_H_PBUFFER (tb->tb_path, h);
dest_bi->bi_parent = PATH_H_PPARENT (tb->tb_path, h);
dest_bi->bi_position = PATH_H_POSITION (tb->tb_path, h + 1); /* dest position is analog of dest->b_item_order */
*d_key = tb->lkey[h];
*cf = tb->CFL[h];
break;
case INTERNAL_SHIFT_FROM_R_TO_S: /* used in internal_shift_left */
src_bi->tb = tb;
src_bi->bi_bh = tb->R[h];
src_bi->bi_parent = tb->FR[h];
src_bi->bi_position = get_right_neighbor_position (tb, h);
dest_bi->tb = tb;
dest_bi->bi_bh = PATH_H_PBUFFER (tb->tb_path, h);
dest_bi->bi_parent = PATH_H_PPARENT (tb->tb_path, h);
dest_bi->bi_position = PATH_H_POSITION (tb->tb_path, h + 1);
*d_key = tb->rkey[h];
*cf = tb->CFR[h];
break;
case INTERNAL_SHIFT_FROM_S_TO_R:
src_bi->tb = tb;
src_bi->bi_bh = PATH_H_PBUFFER (tb->tb_path, h);
src_bi->bi_parent = PATH_H_PPARENT (tb->tb_path, h);
src_bi->bi_position = PATH_H_POSITION (tb->tb_path, h + 1);
dest_bi->tb = tb;
dest_bi->bi_bh = tb->R[h];
dest_bi->bi_parent = tb->FR[h];
dest_bi->bi_position = get_right_neighbor_position (tb, h);
*d_key = tb->rkey[h];
*cf = tb->CFR[h];
break;
case INTERNAL_INSERT_TO_L:
dest_bi->tb =