xfs_bmap_btree.c

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

C
2,360
字号
	if (lbno == NULLFSBLOCK && rbno == NULLFSBLOCK &&	    level == cur->bc_nlevels - 2) {		if ((error = xfs_bmbt_killroot(cur))) {			XFS_BMBT_TRACE_CURSOR(cur, ERROR);			goto error0;		}		if (level > 0 && (error = xfs_bmbt_decrement(cur, level, &i))) {			XFS_BMBT_TRACE_CURSOR(cur, ERROR);			goto error0;		}		XFS_BMBT_TRACE_CURSOR(cur, EXIT);		*stat = 1;		return 0;	}	ASSERT(rbno != NULLFSBLOCK || lbno != NULLFSBLOCK);	if ((error = xfs_btree_dup_cursor(cur, &tcur))) {		XFS_BMBT_TRACE_CURSOR(cur, ERROR);		goto error0;	}	bno = NULLFSBLOCK;	if (rbno != NULLFSBLOCK) {		i = xfs_btree_lastrec(tcur, level);		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);		if ((error = xfs_bmbt_increment(tcur, level, &i))) {			XFS_BMBT_TRACE_CURSOR(cur, ERROR);			goto error0;		}		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);		i = xfs_btree_lastrec(tcur, level);		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);		rbp = tcur->bc_bufs[level];		right = XFS_BUF_TO_BMBT_BLOCK(rbp);#ifdef DEBUG		if ((error = xfs_btree_check_lblock(cur, right, level, rbp))) {			XFS_BMBT_TRACE_CURSOR(cur, ERROR);			goto error0;		}#endif		bno = INT_GET(right->bb_leftsib, ARCH_CONVERT);		if (INT_GET(right->bb_numrecs, ARCH_CONVERT) - 1 >=		    XFS_BMAP_BLOCK_IMINRECS(level, cur)) {			if ((error = xfs_bmbt_lshift(tcur, level, &i))) {				XFS_BMBT_TRACE_CURSOR(cur, ERROR);				goto error0;			}			if (i) {				ASSERT(INT_GET(block->bb_numrecs, ARCH_CONVERT) >=				       XFS_BMAP_BLOCK_IMINRECS(level, tcur));				xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR);				tcur = NULL;				if (level > 0) {					if ((error = xfs_bmbt_decrement(cur,							level, &i))) {						XFS_BMBT_TRACE_CURSOR(cur,							ERROR);						goto error0;					}				}				XFS_BMBT_TRACE_CURSOR(cur, EXIT);				*stat = 1;				return 0;			}		}		rrecs = INT_GET(right->bb_numrecs, ARCH_CONVERT);		if (lbno != NULLFSBLOCK) {			i = xfs_btree_firstrec(tcur, level);			XFS_WANT_CORRUPTED_GOTO(i == 1, error0);			if ((error = xfs_bmbt_decrement(tcur, level, &i))) {				XFS_BMBT_TRACE_CURSOR(cur, ERROR);				goto error0;			}			XFS_WANT_CORRUPTED_GOTO(i == 1, error0);		}	}	if (lbno != NULLFSBLOCK) {		i = xfs_btree_firstrec(tcur, level);		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);		/*		 * decrement to last in block		 */		if ((error = xfs_bmbt_decrement(tcur, level, &i))) {			XFS_BMBT_TRACE_CURSOR(cur, ERROR);			goto error0;		}		i = xfs_btree_firstrec(tcur, level);		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);		lbp = tcur->bc_bufs[level];		left = XFS_BUF_TO_BMBT_BLOCK(lbp);#ifdef DEBUG		if ((error = xfs_btree_check_lblock(cur, left, level, lbp))) {			XFS_BMBT_TRACE_CURSOR(cur, ERROR);			goto error0;		}#endif		bno = INT_GET(left->bb_rightsib, ARCH_CONVERT);		if (INT_GET(left->bb_numrecs, ARCH_CONVERT) - 1 >=		    XFS_BMAP_BLOCK_IMINRECS(level, cur)) {			if ((error = xfs_bmbt_rshift(tcur, level, &i))) {				XFS_BMBT_TRACE_CURSOR(cur, ERROR);				goto error0;			}			if (i) {				ASSERT(INT_GET(block->bb_numrecs, ARCH_CONVERT) >=				       XFS_BMAP_BLOCK_IMINRECS(level, tcur));				xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR);				tcur = NULL;				if (level == 0)					cur->bc_ptrs[0]++;				XFS_BMBT_TRACE_CURSOR(cur, EXIT);				*stat = 1;				return 0;			}		}		lrecs = INT_GET(left->bb_numrecs, ARCH_CONVERT);	}	xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR);	tcur = NULL;	mp = cur->bc_mp;	ASSERT(bno != NULLFSBLOCK);	if (lbno != NULLFSBLOCK &&	    lrecs + INT_GET(block->bb_numrecs, ARCH_CONVERT) <= XFS_BMAP_BLOCK_IMAXRECS(level, cur)) {		rbno = bno;		right = block;		rbp = bp;		if ((error = xfs_btree_read_bufl(mp, cur->bc_tp, lbno, 0, &lbp,				XFS_BMAP_BTREE_REF))) {			XFS_BMBT_TRACE_CURSOR(cur, ERROR);			goto error0;		}		left = XFS_BUF_TO_BMBT_BLOCK(lbp);		if ((error = xfs_btree_check_lblock(cur, left, level, lbp))) {			XFS_BMBT_TRACE_CURSOR(cur, ERROR);			goto error0;		}	} else if (rbno != NULLFSBLOCK &&		   rrecs + INT_GET(block->bb_numrecs, ARCH_CONVERT) <=		   XFS_BMAP_BLOCK_IMAXRECS(level, cur)) {		lbno = bno;		left = block;		lbp = bp;		if ((error = xfs_btree_read_bufl(mp, cur->bc_tp, rbno, 0, &rbp,				XFS_BMAP_BTREE_REF))) {			XFS_BMBT_TRACE_CURSOR(cur, ERROR);			goto error0;		}		right = XFS_BUF_TO_BMBT_BLOCK(rbp);		if ((error = xfs_btree_check_lblock(cur, right, level, rbp))) {			XFS_BMBT_TRACE_CURSOR(cur, ERROR);			goto error0;		}		lrecs = INT_GET(left->bb_numrecs, ARCH_CONVERT);	} else {		if (level > 0 && (error = xfs_bmbt_decrement(cur, level, &i))) {			XFS_BMBT_TRACE_CURSOR(cur, ERROR);			goto error0;		}		XFS_BMBT_TRACE_CURSOR(cur, EXIT);		*stat = 1;		return 0;	}	numlrecs = INT_GET(left->bb_numrecs, ARCH_CONVERT);	numrrecs = INT_GET(right->bb_numrecs, ARCH_CONVERT);	if (level > 0) {		lkp = XFS_BMAP_KEY_IADDR(left, numlrecs + 1, cur);		lpp = XFS_BMAP_PTR_IADDR(left, numlrecs + 1, cur);		rkp = XFS_BMAP_KEY_IADDR(right, 1, cur);		rpp = XFS_BMAP_PTR_IADDR(right, 1, cur);#ifdef DEBUG		for (i = 0; i < numrrecs; i++) {			if ((error = xfs_btree_check_lptr(cur, INT_GET(rpp[i], ARCH_CONVERT), level))) {				XFS_BMBT_TRACE_CURSOR(cur, ERROR);				goto error0;			}		}#endif		memcpy(lkp, rkp, numrrecs * sizeof(*lkp));		memcpy(lpp, rpp, numrrecs * sizeof(*lpp));		xfs_bmbt_log_keys(cur, lbp, numlrecs + 1, numlrecs + numrrecs);		xfs_bmbt_log_ptrs(cur, lbp, numlrecs + 1, numlrecs + numrrecs);	} else {		lrp = XFS_BMAP_REC_IADDR(left, numlrecs + 1, cur);		rrp = XFS_BMAP_REC_IADDR(right, 1, cur);		memcpy(lrp, rrp, numrrecs * sizeof(*lrp));		xfs_bmbt_log_recs(cur, lbp, numlrecs + 1, numlrecs + numrrecs);	}	INT_MOD(left->bb_numrecs, ARCH_CONVERT, numrrecs);	left->bb_rightsib = right->bb_rightsib; /* INT_: direct copy */	xfs_bmbt_log_block(cur, lbp, XFS_BB_RIGHTSIB | XFS_BB_NUMRECS);	if (INT_GET(left->bb_rightsib, ARCH_CONVERT) != NULLDFSBNO) {		if ((error = xfs_btree_read_bufl(mp, cur->bc_tp,				INT_GET(left->bb_rightsib, ARCH_CONVERT),				0, &rrbp, XFS_BMAP_BTREE_REF))) {			XFS_BMBT_TRACE_CURSOR(cur, ERROR);			goto error0;		}		rrblock = XFS_BUF_TO_BMBT_BLOCK(rrbp);		if ((error = xfs_btree_check_lblock(cur, rrblock, level, rrbp))) {			XFS_BMBT_TRACE_CURSOR(cur, ERROR);			goto error0;		}		INT_SET(rrblock->bb_leftsib, ARCH_CONVERT, lbno);		xfs_bmbt_log_block(cur, rrbp, XFS_BB_LEFTSIB);	}	xfs_bmap_add_free(XFS_DADDR_TO_FSB(mp, XFS_BUF_ADDR(rbp)), 1,		cur->bc_private.b.flist, mp);	cur->bc_private.b.ip->i_d.di_nblocks--;	xfs_trans_log_inode(cur->bc_tp, cur->bc_private.b.ip, XFS_ILOG_CORE);	XFS_TRANS_MOD_DQUOT_BYINO(mp, cur->bc_tp, cur->bc_private.b.ip,			XFS_TRANS_DQ_BCOUNT, -1L);	xfs_trans_binval(cur->bc_tp, rbp);	if (bp != lbp) {		cur->bc_bufs[level] = lbp;		cur->bc_ptrs[level] += lrecs;		cur->bc_ra[level] = 0;	} else if ((error = xfs_bmbt_increment(cur, level + 1, &i))) {		XFS_BMBT_TRACE_CURSOR(cur, ERROR);		goto error0;	}	if (level > 0)		cur->bc_ptrs[level]--;	XFS_BMBT_TRACE_CURSOR(cur, EXIT);	*stat = 2;	return 0;error0:	if (tcur)		xfs_btree_del_cursor(tcur, XFS_BTREE_ERROR);	return error;}#ifdef DEBUG/* * Get the data from the pointed-to record. */intxfs_bmbt_get_rec(	xfs_btree_cur_t		*cur,	xfs_fileoff_t		*off,	xfs_fsblock_t		*bno,	xfs_filblks_t		*len,	xfs_exntst_t		*state,	int			*stat){	xfs_bmbt_block_t	*block;	xfs_buf_t		*bp;#ifdef DEBUG	int			error;#endif	int			ptr;	xfs_bmbt_rec_t		*rp;	block = xfs_bmbt_get_block(cur, 0, &bp);	ptr = cur->bc_ptrs[0];#ifdef DEBUG	if ((error = xfs_btree_check_lblock(cur, block, 0, bp)))		return error;#endif	if (ptr > INT_GET(block->bb_numrecs, ARCH_CONVERT) || ptr <= 0) {		*stat = 0;		return 0;	}	rp = XFS_BMAP_REC_IADDR(block, ptr, cur);	*off = xfs_bmbt_disk_get_startoff(rp);	*bno = xfs_bmbt_disk_get_startblock(rp);	*len = xfs_bmbt_disk_get_blockcount(rp);	*state = xfs_bmbt_disk_get_state(rp);	*stat = 1;	return 0;}#endif/* * Insert one record/level.  Return information to the caller * allowing the next level up to proceed if necessary. */STATIC int					/* error */xfs_bmbt_insrec(	xfs_btree_cur_t		*cur,	int			level,	xfs_fsblock_t		*bnop,	xfs_bmbt_rec_t		*recp,	xfs_btree_cur_t		**curp,	int			*stat)		/* no-go/done/continue */{	xfs_bmbt_block_t	*block;		/* bmap btree block */	xfs_buf_t		*bp;		/* buffer for block */	int			error;		/* error return value */#ifdef XFS_BMBT_TRACE	static char		fname[] = "xfs_bmbt_insrec";#endif	int			i;		/* loop index */	xfs_bmbt_key_t		key;		/* bmap btree key */	xfs_bmbt_key_t		*kp=NULL;	/* pointer to bmap btree key */	int			logflags;	/* inode logging flags */	xfs_fsblock_t		nbno;		/* new block number */	struct xfs_btree_cur	*ncur;		/* new btree cursor */	xfs_bmbt_key_t		nkey;		/* new btree key value */	xfs_bmbt_rec_t		nrec;		/* new record count */	int			optr;		/* old key/record index */	xfs_bmbt_ptr_t		*pp;		/* pointer to bmap block addr */	int			ptr;		/* key/record index */	xfs_bmbt_rec_t		*rp=NULL;	/* pointer to bmap btree rec */	int			numrecs;	ASSERT(level < cur->bc_nlevels);	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);	XFS_BMBT_TRACE_ARGIFR(cur, level, *bnop, recp);	ncur = (xfs_btree_cur_t *)0;	INT_SET(key.br_startoff, ARCH_CONVERT,		xfs_bmbt_disk_get_startoff(recp));	optr = ptr = cur->bc_ptrs[level];	if (ptr == 0) {		XFS_BMBT_TRACE_CURSOR(cur, EXIT);		*stat = 0;		return 0;	}	XFS_STATS_INC(xs_bmbt_insrec);	block = xfs_bmbt_get_block(cur, level, &bp);	numrecs = INT_GET(block->bb_numrecs, ARCH_CONVERT);#ifdef DEBUG	if ((error = xfs_btree_check_lblock(cur, block, level, bp))) {		XFS_BMBT_TRACE_CURSOR(cur, ERROR);		return error;	}	if (ptr <= numrecs) {		if (level == 0) {			rp = XFS_BMAP_REC_IADDR(block, ptr, cur);			xfs_btree_check_rec(XFS_BTNUM_BMAP, recp, rp);		} else {			kp = XFS_BMAP_KEY_IADDR(block, ptr, cur);			xfs_btree_check_key(XFS_BTNUM_BMAP, &key, kp);		}	}#endif	nbno = NULLFSBLOCK;	if (numrecs == XFS_BMAP_BLOCK_IMAXRECS(level, cur)) {		if (numrecs < XFS_BMAP_BLOCK_DMAXRECS(level, cur)) {			/*			 * A root block, that can be made bigger.			 */			xfs_iroot_realloc(cur->bc_private.b.ip, 1,				cur->bc_private.b.whichfork);			block = xfs_bmbt_get_block(cur, level, &bp);		} else if (level == cur->bc_nlevels - 1) {			if ((error = xfs_bmbt_newroot(cur, &logflags, stat)) ||			    *stat == 0) {				XFS_BMBT_TRACE_CURSOR(cur, ERROR);				return error;			}			xfs_trans_log_inode(cur->bc_tp, cur->bc_private.b.ip,				logflags);			block = xfs_bmbt_get_block(cur, level, &bp);		} else {			if ((error = xfs_bmbt_rshift(cur, level, &i))) {				XFS_BMBT_TRACE_CURSOR(cur, ERROR);				return error;			}			if (i) {				/* nothing */			} else {				if ((error = xfs_bmbt_lshift(cur, level, &i))) {					XFS_BMBT_TRACE_CURSOR(cur, ERROR);					return error;				}				if (i) {					optr = ptr = cur->bc_ptrs[level];				} else {					if ((error = xfs_bmbt_split(cur, level,							&nbno, &nkey, &ncur,							&i))) {						XFS_BMBT_TRACE_CURSOR(cur,							ERROR);						return error;					}					if (i) {						block = xfs_bmbt_get_block(							    cur, level, &bp);#ifdef DEBUG						if ((error =						    xfs_btree_check_lblock(cur,							    block, level, bp))) {							XFS_BMBT_TRACE_CURSOR(								cur, ERROR);							return error;						}#endif						ptr = cur->bc_ptrs[level];						xfs_bmbt_disk_set_allf(&nrec,							nkey.br_startoff, 0, 0,							XFS_EXT_NORM);					} else {						XFS_BMBT_TRACE_CURSOR(cur,							EXIT);						*stat = 0;						return 0;					}				}			}		}	}	numrecs = INT_GET(block->bb_numrecs, ARCH_CONVERT);	if (level > 0) {		kp = XFS_BMAP_KEY_IADDR(block, 1, cur);		pp = XFS_BMAP_PTR_IADDR(block, 1, cur);#ifdef DEBUG		for (i = numrecs; i >= ptr; i--) {			if ((error = xfs_btree_check_lptr(cur, INT_GET(pp[i - 1], ARCH_CONVERT),					level))) {				XFS_BMBT_TRACE_CURSOR(cur, ERROR);				return error;			}		}#endif		memmove(&kp[ptr], &kp[ptr - 1],			(numrecs - ptr + 1) * sizeof(*kp));		memmove(&pp[ptr], &pp[ptr - 1], /* INT_: direct copy */			(numrecs - ptr + 1) * sizeof(*pp));#ifdef DEBUG		if ((error = xfs_btree_check_lptr(cur, (xfs_bmbt_ptr_t)*bnop,				level))) {			XFS_BMBT_TRACE_CURSOR(cur, ERROR);			return error;		}#endif		kp[ptr - 1] = key;		INT_SET(pp[ptr - 1], ARCH_CONVERT, *bnop);		numrecs++;		INT_SET(block->bb_numrecs, ARCH_CONVERT, numrecs);		xfs_bmbt_log_keys(cur, bp, ptr, numrecs);		xfs_bmbt_log_ptrs(cur, bp, ptr, numrecs);	} else {		rp = XFS_BMAP_REC_IADDR(block, 1, cur);		memmove(&rp[ptr], &rp[ptr - 1],			(numrecs - ptr + 1) * sizeof(*rp));		rp[ptr - 1] = *recp;		numrecs++;		INT_SET(block->bb_numrecs, ARCH_CONVERT, numrecs);		xfs_bmbt_log_recs(cur, bp, ptr, numrecs);	}	xfs_bmbt_log_block(cur, bp, XFS_BB_NUMRECS);#ifdef DEBUG	if (ptr < numrecs) {		if (level == 0)			xfs_btree_check_rec(XFS_BTNUM_BMAP, rp + ptr - 1,				rp + ptr);		else			xfs_btree_check_key(XFS_BTNUM_BMAP, kp + ptr - 1,				kp + ptr);	}#endif	if (optr == 1 && (error = xfs_bmbt_updkey(cur, &key, level + 1))) {		XFS_BMBT_TRACE_CURSOR(cur, ERROR);		return error;	}	*bnop = nbno;	if (nbno != NULLFSBLOCK) {		*recp = nrec;		*curp = ncur;	}	XFS_BMBT_TRACE_CURSOR(cur, EXIT);	*stat = 1;	return 0;}STATIC intxfs_bmbt_killroot(	xfs_btree_cur_t		*cur){	xfs_bmbt_block_t	*block;	xfs_bmbt_block_t	*cblock;	xfs_buf_t		*cbp;	xfs_bmbt_key_t		*ckp;

⌨️ 快捷键说明

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