⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 do_balan.c

📁 ARM 嵌入式 系统 设计与实例开发 实验教材 二源码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README *//* Now we have all buffers that must be used in balancing of the tree 	*//* Further calculations can not cause schedule(), and thus the buffer 	*//* tree will be stable until the balancing will be finished 		*//* balance the tree according to the analysis made before,		*//* and using buffers obtained after all above.				*//** ** balance_leaf_when_delete ** balance_leaf ** do_balance ** **/#include <linux/config.h>#include <asm/uaccess.h>#include <linux/sched.h>#include <linux/reiserfs_fs.h>#ifdef CONFIG_REISERFS_CHECKstruct tree_balance * cur_tb = NULL; /* detects whether more than one                                        copy of tb exists as a means                                        of checking whether schedule                                        is interrupting do_balance */#endifinline void do_balance_mark_leaf_dirty (struct tree_balance * tb, 					struct buffer_head * bh, int flag){    if (reiserfs_dont_log(tb->tb_sb)) {	if (!test_and_set_bit(BH_Dirty, &bh->b_state)) {	    __mark_buffer_dirty(bh) ;	    tb->need_balance_dirty = 1;	}    } else {	int windex = push_journal_writer("do_balance") ;	journal_mark_dirty(tb->transaction_handle, tb->transaction_handle->t_super, bh) ;	pop_journal_writer(windex) ;    }}#define do_balance_mark_internal_dirty do_balance_mark_leaf_dirty#define do_balance_mark_sb_dirty do_balance_mark_leaf_dirty/* summary:  if deleting something ( tb->insert_size[0] < 0 )   return(balance_leaf_when_delete()); (flag d handled here) else   if lnum is larger than 0 we put items into the left node   if rnum is larger than 0 we put items into the right node   if snum1 is larger than 0 we put items into the new node s1   if snum2 is larger than 0 we put items into the new node s2 Note that all *num* count new items being created.It would be easier to read balance_leaf() if each of these summarylines was a separate procedure rather than being inlined.  I thinkthat there are many passages here and in balance_leaf_when_delete() inwhich two calls to one procedure can replace two passages, and itmight save cache space and improve software maintenance costs to do so.  Vladimir made the perceptive comment that we should offload most ofthe decision making in this function into fix_nodes/check_balance, andthen create some sort of structure in tb that says what actions shouldbe performed by do_balance.-Hans *//* Balance leaf node in case of delete or cut: insert_size[0] < 0 * * lnum, rnum can have values >= -1 *	-1 means that the neighbor must be joined with S *	 0 means that nothing should be done with the neighbor *	>0 means to shift entirely or partly the specified number of items to the neighbor */static int balance_leaf_when_delete (struct tree_balance * tb, int flag){    struct buffer_head * tbS0 = PATH_PLAST_BUFFER (tb->tb_path);    int item_pos = PATH_LAST_POSITION (tb->tb_path);    int pos_in_item = tb->tb_path->pos_in_item;    struct buffer_info bi;    int n;    struct item_head * ih;    RFALSE( tb->FR[0] && B_LEVEL (tb->FR[0]) != DISK_LEAF_NODE_LEVEL + 1,	    "vs- 12000: level: wrong FR %z\n", tb->FR[0]);    RFALSE( tb->blknum[0] > 1,	    "PAP-12005: tb->blknum == %d, can not be > 1", tb->blknum[0]);    RFALSE( ! tb->blknum[0] && ! PATH_H_PPARENT(tb->tb_path, 0),	    "PAP-12010: tree can not be empty");    ih = B_N_PITEM_HEAD (tbS0, item_pos);    /* Delete or truncate the item */    switch (flag) {    case M_DELETE:   /* delete item in S[0] */	RFALSE( ih_item_len(ih) + IH_SIZE != -tb->insert_size[0],	        "vs-12013: mode Delete, insert size %d, ih to be deleted %h", 		 -tb->insert_size [0], ih);	bi.tb = tb;	bi.bi_bh = tbS0;	bi.bi_parent = PATH_H_PPARENT (tb->tb_path, 0);	bi.bi_position = PATH_H_POSITION (tb->tb_path, 1);	leaf_delete_items (&bi, 0, item_pos, 1, -1);	if ( ! item_pos && tb->CFL[0] ) {	    if ( B_NR_ITEMS(tbS0) ) {		replace_key(tb, tb->CFL[0],tb->lkey[0],tbS0,0);	    }	    else {		if ( ! PATH_H_POSITION (tb->tb_path, 1) )		    replace_key(tb, tb->CFL[0],tb->lkey[0],PATH_H_PPARENT(tb->tb_path, 0),0);	    }	} 	RFALSE( ! item_pos && !tb->CFL[0],		"PAP-12020: tb->CFL[0]==%p, tb->L[0]==%p", tb->CFL[0], tb->L[0]);    	break;    case M_CUT: {  /* cut item in S[0] */	bi.tb = tb;	bi.bi_bh = tbS0;	bi.bi_parent = PATH_H_PPARENT (tb->tb_path, 0);	bi.bi_position = PATH_H_POSITION (tb->tb_path, 1);	if (is_direntry_le_ih (ih)) {	    /* UFS unlink semantics are such that you can only delete one directory entry at a time. */	    /* when we cut a directory tb->insert_size[0] means number of entries to be cut (always 1) */	    tb->insert_size[0] = -1;	    leaf_cut_from_buffer (&bi, item_pos, pos_in_item, -tb->insert_size[0]);	    RFALSE( ! item_pos && ! pos_in_item && ! tb->CFL[0],		    "PAP-12030: can not change delimiting key. CFL[0]=%p", 		    tb->CFL[0]);	    if ( ! item_pos && ! pos_in_item && tb->CFL[0] ) {		replace_key(tb, tb->CFL[0],tb->lkey[0],tbS0,0);	    }	} else {	    leaf_cut_from_buffer (&bi, item_pos, pos_in_item, -tb->insert_size[0]);	    RFALSE( ! ih_item_len(ih),		"PAP-12035: cut must leave non-zero dynamic length of item");	}	break;    }    default:	print_cur_tb ("12040");	reiserfs_panic (tb->tb_sb, "PAP-12040: balance_leaf_when_delete: unexpectable mode: %s(%d)",			(flag == M_PASTE) ? "PASTE" : ((flag == M_INSERT) ? "INSERT" : "UNKNOWN"), flag);    }    /* the rule is that no shifting occurs unless by shifting a node can be freed */    n = B_NR_ITEMS(tbS0);    if ( tb->lnum[0] )     /* L[0] takes part in balancing */    {	if ( tb->lnum[0] == -1 )    /* L[0] must be joined with S[0] */	{	    if ( tb->rnum[0] == -1 )    /* R[0] must be also joined with S[0] */	    {					if ( tb->FR[0] == PATH_H_PPARENT(tb->tb_path, 0) )		{		    /* all contents of all the 3 buffers will be in L[0] */		    if ( PATH_H_POSITION (tb->tb_path, 1) == 0 && 1 < B_NR_ITEMS(tb->FR[0]) )			replace_key(tb, tb->CFL[0],tb->lkey[0],tb->FR[0],1);		    leaf_move_items (LEAF_FROM_S_TO_L, tb, n, -1, 0);		    leaf_move_items (LEAF_FROM_R_TO_L, tb, B_NR_ITEMS(tb->R[0]), -1, 0);		    reiserfs_invalidate_buffer (tb, tbS0);		    reiserfs_invalidate_buffer (tb, tb->R[0]);		    return 0;		}		/* all contents of all the 3 buffers will be in R[0] */		leaf_move_items (LEAF_FROM_S_TO_R, tb, n, -1, 0);		leaf_move_items (LEAF_FROM_L_TO_R, tb, B_NR_ITEMS(tb->L[0]), -1, 0);		/* right_delimiting_key is correct in R[0] */		replace_key(tb, tb->CFR[0],tb->rkey[0],tb->R[0],0);		reiserfs_invalidate_buffer (tb, tbS0);		reiserfs_invalidate_buffer (tb, tb->L[0]);		return -1;	    }	    RFALSE( tb->rnum[0] != 0, 		    "PAP-12045: rnum must be 0 (%d)", tb->rnum[0]);	    /* all contents of L[0] and S[0] will be in L[0] */	    leaf_shift_left(tb, n, -1);	    reiserfs_invalidate_buffer (tb, tbS0);	    return 0;	}	/* a part of contents of S[0] will be in L[0] and the rest part of S[0] will be in R[0] */	RFALSE( ( tb->lnum[0] + tb->rnum[0] < n ) || 		( tb->lnum[0] + tb->rnum[0] > n+1 ),		"PAP-12050: rnum(%d) and lnum(%d) and item number(%d) in S[0] are not consistent",		tb->rnum[0], tb->lnum[0], n);	RFALSE( ( tb->lnum[0] + tb->rnum[0] == n ) && 		(tb->lbytes != -1 || tb->rbytes != -1),		"PAP-12055: bad rbytes (%d)/lbytes (%d) parameters when items are not split", 		tb->rbytes, tb->lbytes);	RFALSE( ( tb->lnum[0] + tb->rnum[0] == n + 1 ) && 		(tb->lbytes < 1 || tb->rbytes != -1),		"PAP-12060: bad rbytes (%d)/lbytes (%d) parameters when items are split", 		tb->rbytes, tb->lbytes);	leaf_shift_left (tb, tb->lnum[0], tb->lbytes);	leaf_shift_right(tb, tb->rnum[0], tb->rbytes);	reiserfs_invalidate_buffer (tb, tbS0);	return 0;    }    if ( tb->rnum[0] == -1 ) {	/* all contents of R[0] and S[0] will be in R[0] */	leaf_shift_right(tb, n, -1);	reiserfs_invalidate_buffer (tb, tbS0);	return 0;    }    RFALSE( tb->rnum[0], 	    "PAP-12065: bad rnum parameter must be 0 (%d)", tb->rnum[0]);    return 0;}static int balance_leaf (struct tree_balance * tb,			 struct item_head * ih,		/* item header of inserted item (this is on little endian) */			 const char * body,		/* body  of inserted item or bytes to paste */			 int flag,			/* i - insert, d - delete, c - cut, p - paste							   (see comment to do_balance) */			 struct item_head * insert_key,  /* in our processing of one level we sometimes determine what							    must be inserted into the next higher level.  This insertion							    consists of a key or two keys and their corresponding							    pointers */			 struct buffer_head ** insert_ptr /* inserted node-ptrs for the next level */    ){    struct buffer_head * tbS0 = PATH_PLAST_BUFFER (tb->tb_path);    int item_pos = PATH_LAST_POSITION (tb->tb_path);	/*  index into the array of item headers in S[0] 							    of the affected item */    struct buffer_info bi;    struct buffer_head *S_new[2];  /* new nodes allocated to hold what could not fit into S */    int snum[2];	    /* number of items that will be placed                               into S_new (includes partially shifted                               items) */    int sbytes[2];          /* if an item is partially shifted into S_new then 			       if it is a directory item 			       it is the number of entries from the item that are shifted into S_new			       else			       it is the number of bytes from the item that are shifted into S_new			    */    int n, i;    int ret_val;    int pos_in_item;    int zeros_num;    PROC_INFO_INC( tb -> tb_sb, balance_at[ 0 ] );    /* Make balance in case insert_size[0] < 0 */    if ( tb->insert_size[0] < 0 )	return balance_leaf_when_delete (tb, flag);      zeros_num = 0;    if (flag == M_INSERT && body == 0)	zeros_num = ih_item_len( ih );    pos_in_item = tb->tb_path->pos_in_item;    /* for indirect item pos_in_item is measured in unformatted node       pointers. Recalculate to bytes */    if (flag != M_INSERT && is_indirect_le_ih (B_N_PITEM_HEAD (tbS0, item_pos)))	pos_in_item *= UNFM_P_SIZE;    if ( tb->lnum[0] > 0 ) {	/* Shift lnum[0] items from S[0] to the left neighbor L[0] */	if ( item_pos < tb->lnum[0] ) {	    /* new item or it part falls to L[0], shift it too */	    n = B_NR_ITEMS(tb->L[0]);	    switch (flag) {	    case M_INSERT:   /* insert item into L[0] */		if ( item_pos == tb->lnum[0] - 1 && tb->lbytes != -1 ) {		    /* part of new item falls into L[0] */		    int new_item_len;		    int version;		    RFALSE (!is_direct_le_ih (ih),			    "PAP-12075: only direct inserted item can be broken. %h", ih);		    ret_val = leaf_shift_left (tb, tb->lnum[0]-1, -1);		    /* Calculate item length to insert to S[0] */		    new_item_len = ih_item_len(ih) - tb->lbytes;		    /* Calculate and check item length to insert to L[0] */		    put_ih_item_len(ih, ih_item_len(ih) - new_item_len );		    RFALSE( ih_item_len(ih) <= 0,			    "PAP-12080: there is nothing to insert into L[0]: ih_item_len=%d",                            ih_item_len(ih));		    /* Insert new item into L[0] */		    bi.tb = tb;		    bi.bi_bh = tb->L[0];		    bi.bi_parent = tb->FL[0];		    bi.bi_position = get_left_neighbor_position (tb, 0);		    leaf_insert_into_buf (&bi, n + item_pos - ret_val, ih, body,					  zeros_num > ih_item_len(ih) ? ih_item_len(ih) : zeros_num);		    version = ih_version (ih);		    /* Calculate key component, item length and body to insert into S[0] */                    set_le_ih_k_offset( ih, le_ih_k_offset( ih ) + tb->lbytes );		    put_ih_item_len( ih, new_item_len );		    if ( tb->lbytes >  zeros_num ) {			body += (tb->lbytes - zeros_num);			zeros_num = 0;		    }		    else			zeros_num -= tb->lbytes;		    RFALSE( ih_item_len(ih) <= 0,			"PAP-12085: there is nothing to insert into S[0]: ih_item_len=%d",			ih_item_len(ih));		} else {		    /* new item in whole falls into L[0] */		    /* Shift lnum[0]-1 items to L[0] */		    ret_val = leaf_shift_left(tb, tb->lnum[0]-1, tb->lbytes);		    /* Insert new item into L[0] */		    bi.tb = tb;		    bi.bi_bh = tb->L[0];		    bi.bi_parent = tb->FL[0];		    bi.bi_position = get_left_neighbor_position (tb, 0);		    leaf_insert_into_buf (&bi, n + item_pos - ret_val, ih, body, zeros_num);		    tb->insert_size[0] = 0;		    zeros_num = 0;		}		break;	    case M_PASTE:   /* append item in L[0] */		if ( item_pos == tb->lnum[0] - 1 && tb->lbytes != -1 ) {		    /* we must shift the part of the appended item */		    if ( is_direntry_le_ih (B_N_PITEM_HEAD (tbS0, item_pos))) {			RFALSE( zeros_num,				"PAP-12090: illegal parameter in case of a directory");			/* directory item */			if ( tb->lbytes > pos_in_item ) {			    /* new directory entry falls into L[0] */			    struct item_head * pasted;			    int l_pos_in_item = pos_in_item;							  			    /* Shift lnum[0] - 1 items in whole. Shift lbytes - 1 entries from given directory item */			    ret_val = leaf_shift_left(tb, tb->lnum[0], tb->lbytes - 1);			    if ( ret_val && ! item_pos ) {				pasted =  B_N_PITEM_HEAD(tb->L[0],B_NR_ITEMS(tb->L[0])-1);				l_pos_in_item += I_ENTRY_COUNT(pasted) - (tb->lbytes-1);			    }			    /* Append given directory entry to directory item */			    bi.tb = tb;			    bi.bi_bh = tb->L[0];			    bi.bi_parent = tb->FL[0];			    bi.bi_position = get_left_neighbor_position (tb, 0);			    leaf_paste_in_buffer (&bi, n + item_pos - ret_val, l_pos_in_item,						  tb->insert_size[0], body, zeros_num);			    /* previous string prepared space for pasting new entry, following string pastes this entry */			    /* when we have merge directory item, pos_in_item has been changed too */			    /* paste new directory entry. 1 is entry number */			    leaf_paste_entries (bi.bi_bh, n + item_pos - ret_val, l_pos_in_item, 1,						(struct reiserfs_de_head *)body, 						body + DEH_SIZE, tb->insert_size[0]				);			    tb->insert_size[0] = 0;			} else {			    /* new directory item doesn't fall into L[0] */			    /* Shift lnum[0]-1 items in whole. Shift lbytes directory entries from directory item number lnum[0] */			    leaf_shift_left (tb, tb->lnum[0], tb->lbytes);			}			/* Calculate new position to append in item body */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -