xfs_alloc_btree.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 2,070 行 · 第 1/5 页

C
2,070
字号
				return error;		}#endif		memcpy(rkp, lkp, INT_GET(right->bb_numrecs, ARCH_CONVERT) * sizeof(*rkp)); /* INT_: copy */		memcpy(rpp, lpp, INT_GET(right->bb_numrecs, ARCH_CONVERT) * sizeof(*rpp)); /* INT_: copy */		xfs_alloc_log_keys(cur, rbp, 1, INT_GET(right->bb_numrecs, ARCH_CONVERT));		xfs_alloc_log_ptrs(cur, rbp, 1, INT_GET(right->bb_numrecs, ARCH_CONVERT));		*keyp = *rkp;	}	/*	 * For leaf blocks, copy records over to the new block.	 */	else {		xfs_alloc_rec_t	*lrp;	/* left btree record pointer */		xfs_alloc_rec_t	*rrp;	/* right btree record pointer */		lrp = XFS_ALLOC_REC_ADDR(left, i, cur);		rrp = XFS_ALLOC_REC_ADDR(right, 1, cur);		memcpy(rrp, lrp, INT_GET(right->bb_numrecs, ARCH_CONVERT) * sizeof(*rrp));		xfs_alloc_log_recs(cur, rbp, 1, INT_GET(right->bb_numrecs, ARCH_CONVERT));		keyp->ar_startblock = rrp->ar_startblock; /* INT_: direct copy */		keyp->ar_blockcount = rrp->ar_blockcount; /* INT_: direct copy */	}	/*	 * Find the left block number by looking in the buffer.	 * Adjust numrecs, sibling pointers.	 */	lbno = XFS_DADDR_TO_AGBNO(cur->bc_mp, XFS_BUF_ADDR(lbp));	INT_MOD(left->bb_numrecs, ARCH_CONVERT, -(INT_GET(right->bb_numrecs, ARCH_CONVERT)));	right->bb_rightsib = left->bb_rightsib; /* INT_: direct copy */	INT_SET(left->bb_rightsib, ARCH_CONVERT, rbno);	INT_SET(right->bb_leftsib, ARCH_CONVERT, lbno);	xfs_alloc_log_block(cur->bc_tp, rbp, XFS_BB_ALL_BITS);	xfs_alloc_log_block(cur->bc_tp, lbp, XFS_BB_NUMRECS | XFS_BB_RIGHTSIB);	/*	 * If there's a block to the new block's right, make that block	 * point back to right instead of to left.	 */	if (INT_GET(right->bb_rightsib, ARCH_CONVERT) != NULLAGBLOCK) {		xfs_alloc_block_t	*rrblock;	/* rr btree block */		xfs_buf_t		*rrbp;		/* buffer for rrblock */		if ((error = xfs_btree_read_bufs(cur->bc_mp, cur->bc_tp,				cur->bc_private.a.agno, INT_GET(right->bb_rightsib, ARCH_CONVERT), 0,				&rrbp, XFS_ALLOC_BTREE_REF)))			return error;		rrblock = XFS_BUF_TO_ALLOC_BLOCK(rrbp);		if ((error = xfs_btree_check_sblock(cur, rrblock, level, rrbp)))			return error;		INT_SET(rrblock->bb_leftsib, ARCH_CONVERT, rbno);		xfs_alloc_log_block(cur->bc_tp, rrbp, XFS_BB_LEFTSIB);	}	/*	 * If the cursor is really in the right block, move it there.	 * If it's just pointing past the last entry in left, then we'll	 * insert there, so don't change anything in that case.	 */	if (cur->bc_ptrs[level] > INT_GET(left->bb_numrecs, ARCH_CONVERT) + 1) {		xfs_btree_setbuf(cur, level, rbp);		cur->bc_ptrs[level] -= INT_GET(left->bb_numrecs, ARCH_CONVERT);	}	/*	 * If there are more levels, we'll need another cursor which refers to	 * the right block, no matter where this cursor was.	 */	if (level + 1 < cur->bc_nlevels) {		if ((error = xfs_btree_dup_cursor(cur, curp)))			return error;		(*curp)->bc_ptrs[level + 1]++;	}	*bnop = rbno;	*stat = 1;	return 0;}/* * Update keys at all levels from here to the root along the cursor's path. */STATIC int				/* error */xfs_alloc_updkey(	xfs_btree_cur_t		*cur,	/* btree cursor */	xfs_alloc_key_t		*keyp,	/* new key value to update to */	int			level)	/* starting level for update */{	int			ptr;	/* index of key in block */	/*	 * Go up the tree from this level toward the root.	 * At each level, update the key value to the value input.	 * Stop when we reach a level where the cursor isn't pointing	 * at the first entry in the block.	 */	for (ptr = 1; ptr == 1 && level < cur->bc_nlevels; level++) {		xfs_alloc_block_t	*block;	/* btree block */		xfs_buf_t		*bp;	/* buffer for block */#ifdef DEBUG		int			error;	/* error return value */#endif		xfs_alloc_key_t		*kp;	/* ptr to btree block keys */		bp = cur->bc_bufs[level];		block = XFS_BUF_TO_ALLOC_BLOCK(bp);#ifdef DEBUG		if ((error = xfs_btree_check_sblock(cur, block, level, bp)))			return error;#endif		ptr = cur->bc_ptrs[level];		kp = XFS_ALLOC_KEY_ADDR(block, ptr, cur);		*kp = *keyp;		xfs_alloc_log_keys(cur, bp, ptr, ptr);	}	return 0;}/* * Externally visible routines. *//* * Decrement cursor by one record at the level. * For nonzero levels the leaf-ward information is untouched. */int					/* error */xfs_alloc_decrement(	xfs_btree_cur_t		*cur,	/* btree cursor */	int			level,	/* level in btree, 0 is leaf */	int			*stat)	/* success/failure */{	xfs_alloc_block_t	*block;	/* btree block */	int			error;	/* error return value */	int			lev;	/* btree level */	ASSERT(level < cur->bc_nlevels);	/*	 * Read-ahead to the left at this level.	 */	xfs_btree_readahead(cur, level, XFS_BTCUR_LEFTRA);	/*	 * Decrement the ptr at this level.  If we're still in the block	 * then we're done.	 */	if (--cur->bc_ptrs[level] > 0) {		*stat = 1;		return 0;	}	/*	 * Get a pointer to the btree block.	 */	block = XFS_BUF_TO_ALLOC_BLOCK(cur->bc_bufs[level]);#ifdef DEBUG	if ((error = xfs_btree_check_sblock(cur, block, level,			cur->bc_bufs[level])))		return error;#endif	/*	 * If we just went off the left edge of the tree, return failure.	 */	if (INT_GET(block->bb_leftsib, ARCH_CONVERT) == NULLAGBLOCK) {		*stat = 0;		return 0;	}	/*	 * March up the tree decrementing pointers.	 * Stop when we don't go off the left edge of a block.	 */	for (lev = level + 1; lev < cur->bc_nlevels; lev++) {		if (--cur->bc_ptrs[lev] > 0)			break;		/*		 * Read-ahead the left block, we're going to read it		 * in the next loop.		 */		xfs_btree_readahead(cur, lev, XFS_BTCUR_LEFTRA);	}	/*	 * If we went off the root then we are seriously confused.	 */	ASSERT(lev < cur->bc_nlevels);	/*	 * Now walk back down the tree, fixing up the cursor's buffer	 * pointers and key numbers.	 */	for (block = XFS_BUF_TO_ALLOC_BLOCK(cur->bc_bufs[lev]); lev > level; ) {		xfs_agblock_t	agbno;	/* block number of btree block */		xfs_buf_t	*bp;	/* buffer pointer for block */		agbno = INT_GET(*XFS_ALLOC_PTR_ADDR(block, cur->bc_ptrs[lev], cur), ARCH_CONVERT);		if ((error = xfs_btree_read_bufs(cur->bc_mp, cur->bc_tp,				cur->bc_private.a.agno, agbno, 0, &bp,				XFS_ALLOC_BTREE_REF)))			return error;		lev--;		xfs_btree_setbuf(cur, lev, bp);		block = XFS_BUF_TO_ALLOC_BLOCK(bp);		if ((error = xfs_btree_check_sblock(cur, block, lev, bp)))			return error;		cur->bc_ptrs[lev] = INT_GET(block->bb_numrecs, ARCH_CONVERT);	}	*stat = 1;	return 0;}/* * Delete the record pointed to by cur. * The cursor refers to the place where the record was (could be inserted) * when the operation returns. */int					/* error */xfs_alloc_delete(	xfs_btree_cur_t	*cur,		/* btree cursor */	int		*stat)		/* success/failure */{	int		error;		/* error return value */	int		i;		/* result code */	int		level;		/* btree level */	/*	 * Go up the tree, starting at leaf level.	 * If 2 is returned then a join was done; go to the next level.	 * Otherwise we are done.	 */	for (level = 0, i = 2; i == 2; level++) {		if ((error = xfs_alloc_delrec(cur, level, &i)))			return error;	}	if (i == 0) {		for (level = 1; level < cur->bc_nlevels; level++) {			if (cur->bc_ptrs[level] == 0) {				if ((error = xfs_alloc_decrement(cur, level, &i)))					return error;				break;			}		}	}	*stat = i;	return 0;}/* * Get the data from the pointed-to record. */int					/* error */xfs_alloc_get_rec(	xfs_btree_cur_t		*cur,	/* btree cursor */	xfs_agblock_t		*bno,	/* output: starting block of extent */	xfs_extlen_t		*len,	/* output: length of extent */	int			*stat)	/* output: success/failure */{	xfs_alloc_block_t	*block;	/* btree block */#ifdef DEBUG	int			error;	/* error return value */#endif	int			ptr;	/* record number */	ptr = cur->bc_ptrs[0];	block = XFS_BUF_TO_ALLOC_BLOCK(cur->bc_bufs[0]);#ifdef DEBUG	if ((error = xfs_btree_check_sblock(cur, block, 0, cur->bc_bufs[0])))		return error;#endif	/*	 * Off the right end or left end, return failure.	 */	if (ptr > INT_GET(block->bb_numrecs, ARCH_CONVERT) || ptr <= 0) {		*stat = 0;		return 0;	}	/*	 * Point to the record and extract its data.	 */	{		xfs_alloc_rec_t		*rec;	/* record data */		rec = XFS_ALLOC_REC_ADDR(block, ptr, cur);		*bno = INT_GET(rec->ar_startblock, ARCH_CONVERT);		*len = INT_GET(rec->ar_blockcount, ARCH_CONVERT);	}	*stat = 1;	return 0;}/* * Increment cursor by one record at the level. * For nonzero levels the leaf-ward information is untouched. */int					/* error */xfs_alloc_increment(	xfs_btree_cur_t		*cur,	/* btree cursor */	int			level,	/* level in btree, 0 is leaf */	int			*stat)	/* success/failure */{	xfs_alloc_block_t	*block;	/* btree block */	xfs_buf_t		*bp;	/* tree block buffer */	int			error;	/* error return value */	int			lev;	/* btree level */	ASSERT(level < cur->bc_nlevels);	/*	 * Read-ahead to the right at this level.	 */	xfs_btree_readahead(cur, level, XFS_BTCUR_RIGHTRA);	/*	 * Get a pointer to the btree block.	 */	bp = cur->bc_bufs[level];	block = XFS_BUF_TO_ALLOC_BLOCK(bp);#ifdef DEBUG	if ((error = xfs_btree_check_sblock(cur, block, level, bp)))		return error;#endif	/*	 * Increment the ptr at this level.  If we're still in the block	 * then we're done.	 */	if (++cur->bc_ptrs[level] <= INT_GET(block->bb_numrecs, ARCH_CONVERT)) {		*stat = 1;		return 0;	}	/*	 * If we just went off the right edge of the tree, return failure.	 */	if (INT_GET(block->bb_rightsib, ARCH_CONVERT) == NULLAGBLOCK) {		*stat = 0;		return 0;	}	/*	 * March up the tree incrementing pointers.	 * Stop when we don't go off the right edge of a block.	 */	for (lev = level + 1; lev < cur->bc_nlevels; lev++) {		bp = cur->bc_bufs[lev];		block = XFS_BUF_TO_ALLOC_BLOCK(bp);#ifdef DEBUG		if ((error = xfs_btree_check_sblock(cur, block, lev, bp)))			return error;#endif		if (++cur->bc_ptrs[lev] <= INT_GET(block->bb_numrecs, ARCH_CONVERT))			break;		/*		 * Read-ahead the right block, we're going to read it		 * in the next loop.		 */		xfs_btree_readahead(cur, lev, XFS_BTCUR_RIGHTRA);	}	/*	 * If we went off the root then we are seriously confused.	 */	ASSERT(lev < cur->bc_nlevels);	/*	 * Now walk back down the tree, fixing up the cursor's buffer	 * pointers and key numbers.	 */	for (bp = cur->bc_bufs[lev], block = XFS_BUF_TO_ALLOC_BLOCK(bp);	     lev > level; ) {		xfs_agblock_t	agbno;	/* block number of btree block */		agbno = INT_GET(*XFS_ALLOC_PTR_ADDR(block, cur->bc_ptrs[lev], cur), ARCH_CONVERT);		if ((error = xfs_btree_read_bufs(cur->bc_mp, cur->bc_tp,				cur->bc_private.a.agno, agbno, 0, &bp,				XFS_ALLOC_BTREE_REF)))			return error;		lev--;		xfs_btree_setbuf(cur, lev, bp);		block = XFS_BUF_TO_ALLOC_BLOCK(bp);		if ((error = xfs_btree_check_sblock(cur, block, lev, bp)))			return error;		cur->bc_ptrs[lev] = 1;	}	*stat = 1;	return 0;}/* * Insert the current record at the point referenced by cur. * The cursor may be inconsistent on return if splits have been done. */int					/* error */xfs_alloc_insert(	xfs_btree_cur_t	*cur,		/* btree cursor */	int		*stat)		/* success/failure */{	int		error;		/* error return value */	int		i;		/* result value, 0 for failure */	int		level;		/* current level number in btree */	xfs_agblock_t	nbno;		/* new block number (split result) */	xfs_btree_cur_t	*ncur;		/* new cursor (split result) */	xfs_alloc_rec_t	nrec;		/* record being inserted this level */	xfs_btree_cur_t	*pcur;		/* previous level's cursor */	level = 0;	nbno = NULLAGBLOCK;	INT_SET(nrec.ar_startblock, ARCH_CONVERT, cur->bc_rec.a.ar_startblock);	INT_SET(nrec.ar_blockcount, ARCH_CONVERT, cur->bc_rec.a.ar_blockcount);	ncur = (xfs_btree_cur_t *)0;	pcur = cur;	/*	 * Loop going up the tree, starting at the leaf level.	 * Stop when we don't get a split block, that must mean that	 * the insert is finished with this level.	 */	do {		/*		 * Insert nrec/nbno into this level of the tree.		 * Note if we fail, nbno will be null.		 */		if ((error = xfs_alloc_insrec(pcur, level++, &nbno, &nrec, &ncur,				&i))) {			if (pcur != cur)				xfs_btree_del_cursor(pcur, XFS_BTREE_ERROR);			return error;		}		/*		 * See if the cursor we just used is trash.		 * Can't trash the 

⌨️ 快捷键说明

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