/*
* Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
*/
#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