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

📄 xfs_btree.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	 * Get the block pointer for this level.	 */	block = xfs_btree_get_block(cur, level, &bp);	xfs_btree_check_block(cur, block, level, bp);	/*	 * It's empty, there is no such record.	 */	if (!block->bb_h.bb_numrecs)		return 0;	/*	 * Set the ptr value to 1, that's the first record/key.	 */	cur->bc_ptrs[level] = 1;	return 1;}/* * Retrieve the block pointer from the cursor at the given level. * This may be a bmap btree root or from a buffer. */STATIC xfs_btree_block_t *		/* generic btree block pointer */xfs_btree_get_block(	xfs_btree_cur_t		*cur,	/* btree cursor */	int			level,	/* level in btree */	xfs_buf_t		**bpp)	/* buffer containing the block */{	xfs_btree_block_t	*block;	/* return value */	xfs_buf_t		*bp;	/* return buffer */	xfs_ifork_t		*ifp;	/* inode fork pointer */	int			whichfork; /* data or attr fork */	if (cur->bc_btnum == XFS_BTNUM_BMAP && level == cur->bc_nlevels - 1) {		whichfork = cur->bc_private.b.whichfork;		ifp = XFS_IFORK_PTR(cur->bc_private.b.ip, whichfork);		block = (xfs_btree_block_t *)ifp->if_broot;		bp = NULL;	} else {		bp = cur->bc_bufs[level];		block = XFS_BUF_TO_BLOCK(bp);	}	ASSERT(block != NULL);	*bpp = bp;	return block;}/* * Get a buffer for the block, return it with no data read. * Long-form addressing. */xfs_buf_t *				/* buffer for fsbno */xfs_btree_get_bufl(	xfs_mount_t	*mp,		/* file system mount point */	xfs_trans_t	*tp,		/* transaction pointer */	xfs_fsblock_t	fsbno,		/* file system block number */	uint		lock)		/* lock flags for get_buf */{	xfs_buf_t	*bp;		/* buffer pointer (return value) */	xfs_daddr_t		d;		/* real disk block address */	ASSERT(fsbno != NULLFSBLOCK);	d = XFS_FSB_TO_DADDR(mp, fsbno);	bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, d, mp->m_bsize, lock);	ASSERT(bp);	ASSERT(!XFS_BUF_GETERROR(bp));	return bp;}/* * Get a buffer for the block, return it with no data read. * Short-form addressing. */xfs_buf_t *				/* buffer for agno/agbno */xfs_btree_get_bufs(	xfs_mount_t	*mp,		/* file system mount point */	xfs_trans_t	*tp,		/* transaction pointer */	xfs_agnumber_t	agno,		/* allocation group number */	xfs_agblock_t	agbno,		/* allocation group block number */	uint		lock)		/* lock flags for get_buf */{	xfs_buf_t	*bp;		/* buffer pointer (return value) */	xfs_daddr_t		d;		/* real disk block address */	ASSERT(agno != NULLAGNUMBER);	ASSERT(agbno != NULLAGBLOCK);	d = XFS_AGB_TO_DADDR(mp, agno, agbno);	bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, d, mp->m_bsize, lock);	ASSERT(bp);	ASSERT(!XFS_BUF_GETERROR(bp));	return bp;}/* * Allocate a new btree cursor. * The cursor is either for allocation (A) or bmap (B) or inodes (I). */xfs_btree_cur_t *			/* new btree cursor */xfs_btree_init_cursor(	xfs_mount_t	*mp,		/* file system mount point */	xfs_trans_t	*tp,		/* transaction pointer */	xfs_buf_t	*agbp,		/* (A only) buffer for agf structure */					/* (I only) buffer for agi structure */	xfs_agnumber_t	agno,		/* (AI only) allocation group number */	xfs_btnum_t	btnum,		/* btree identifier */	xfs_inode_t	*ip,		/* (B only) inode owning the btree */	int		whichfork)	/* (B only) data or attr fork */{	xfs_agf_t	*agf;		/* (A) allocation group freespace */	xfs_agi_t	*agi;		/* (I) allocation group inodespace */	xfs_btree_cur_t	*cur;		/* return value */	xfs_ifork_t	*ifp;		/* (I) inode fork pointer */	int		nlevels=0;	/* number of levels in the btree */	ASSERT(xfs_btree_cur_zone != NULL);	/*	 * Allocate a new cursor.	 */	cur = kmem_zone_zalloc(xfs_btree_cur_zone, KM_SLEEP);	/*	 * Deduce the number of btree levels from the arguments.	 */	switch (btnum) {	case XFS_BTNUM_BNO:	case XFS_BTNUM_CNT:		agf = XFS_BUF_TO_AGF(agbp);		nlevels = be32_to_cpu(agf->agf_levels[btnum]);		break;	case XFS_BTNUM_BMAP:		ifp = XFS_IFORK_PTR(ip, whichfork);		nlevels = be16_to_cpu(ifp->if_broot->bb_level) + 1;		break;	case XFS_BTNUM_INO:		agi = XFS_BUF_TO_AGI(agbp);		nlevels = be32_to_cpu(agi->agi_level);		break;	default:		ASSERT(0);	}	/*	 * Fill in the common fields.	 */	cur->bc_tp = tp;	cur->bc_mp = mp;	cur->bc_nlevels = nlevels;	cur->bc_btnum = btnum;	cur->bc_blocklog = mp->m_sb.sb_blocklog;	/*	 * Fill in private fields.	 */	switch (btnum) {	case XFS_BTNUM_BNO:	case XFS_BTNUM_CNT:		/*		 * Allocation btree fields.		 */		cur->bc_private.a.agbp = agbp;		cur->bc_private.a.agno = agno;		break;	case XFS_BTNUM_BMAP:		/*		 * Bmap btree fields.		 */		cur->bc_private.b.forksize = XFS_IFORK_SIZE(ip, whichfork);		cur->bc_private.b.ip = ip;		cur->bc_private.b.firstblock = NULLFSBLOCK;		cur->bc_private.b.flist = NULL;		cur->bc_private.b.allocated = 0;		cur->bc_private.b.flags = 0;		cur->bc_private.b.whichfork = whichfork;		break;	case XFS_BTNUM_INO:		/*		 * Inode allocation btree fields.		 */		cur->bc_private.i.agbp = agbp;		cur->bc_private.i.agno = agno;		break;	default:		ASSERT(0);	}	return cur;}/* * Check for the cursor referring to the last block at the given level. */int					/* 1=is last block, 0=not last block */xfs_btree_islastblock(	xfs_btree_cur_t		*cur,	/* btree cursor */	int			level)	/* level to check */{	xfs_btree_block_t	*block;	/* generic btree block pointer */	xfs_buf_t		*bp;	/* buffer containing block */	block = xfs_btree_get_block(cur, level, &bp);	xfs_btree_check_block(cur, block, level, bp);	if (XFS_BTREE_LONG_PTRS(cur->bc_btnum))		return be64_to_cpu(block->bb_u.l.bb_rightsib) == NULLDFSBNO;	else		return be32_to_cpu(block->bb_u.s.bb_rightsib) == NULLAGBLOCK;}/* * Change the cursor to point to the last record in the current block * at the given level.  Other levels are unaffected. */int					/* success=1, failure=0 */xfs_btree_lastrec(	xfs_btree_cur_t		*cur,	/* btree cursor */	int			level)	/* level to change */{	xfs_btree_block_t	*block;	/* generic btree block pointer */	xfs_buf_t		*bp;	/* buffer containing block */	/*	 * Get the block pointer for this level.	 */	block = xfs_btree_get_block(cur, level, &bp);	xfs_btree_check_block(cur, block, level, bp);	/*	 * It's empty, there is no such record.	 */	if (!block->bb_h.bb_numrecs)		return 0;	/*	 * Set the ptr value to numrecs, that's the last record/key.	 */	cur->bc_ptrs[level] = be16_to_cpu(block->bb_h.bb_numrecs);	return 1;}/* * Compute first and last byte offsets for the fields given. * Interprets the offsets table, which contains struct field offsets. */voidxfs_btree_offsets(	__int64_t	fields,		/* bitmask of fields */	const short	*offsets,	/* table of field offsets */	int		nbits,		/* number of bits to inspect */	int		*first,		/* output: first byte offset */	int		*last)		/* output: last byte offset */{	int		i;		/* current bit number */	__int64_t	imask;		/* mask for current bit number */	ASSERT(fields != 0);	/*	 * Find the lowest bit, so the first byte offset.	 */	for (i = 0, imask = 1LL; ; i++, imask <<= 1) {		if (imask & fields) {			*first = offsets[i];			break;		}	}	/*	 * Find the highest bit, so the last byte offset.	 */	for (i = nbits - 1, imask = 1LL << i; ; i--, imask >>= 1) {		if (imask & fields) {			*last = offsets[i + 1] - 1;			break;		}	}}/* * Get a buffer for the block, return it read in. * Long-form addressing. */int					/* error */xfs_btree_read_bufl(	xfs_mount_t	*mp,		/* file system mount point */	xfs_trans_t	*tp,		/* transaction pointer */	xfs_fsblock_t	fsbno,		/* file system block number */	uint		lock,		/* lock flags for read_buf */	xfs_buf_t	**bpp,		/* buffer for fsbno */	int		refval)		/* ref count value for buffer */{	xfs_buf_t	*bp;		/* return value */	xfs_daddr_t		d;		/* real disk block address */	int		error;	ASSERT(fsbno != NULLFSBLOCK);	d = XFS_FSB_TO_DADDR(mp, fsbno);	if ((error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, d,			mp->m_bsize, lock, &bp))) {		return error;	}	ASSERT(!bp || !XFS_BUF_GETERROR(bp));	if (bp != NULL) {		XFS_BUF_SET_VTYPE_REF(bp, B_FS_MAP, refval);	}	*bpp = bp;	return 0;}/* * Get a buffer for the block, return it read in. * Short-form addressing. */int					/* error */xfs_btree_read_bufs(	xfs_mount_t	*mp,		/* file system mount point */	xfs_trans_t	*tp,		/* transaction pointer */	xfs_agnumber_t	agno,		/* allocation group number */	xfs_agblock_t	agbno,		/* allocation group block number */	uint		lock,		/* lock flags for read_buf */	xfs_buf_t	**bpp,		/* buffer for agno/agbno */	int		refval)		/* ref count value for buffer */{	xfs_buf_t	*bp;		/* return value */	xfs_daddr_t	d;		/* real disk block address */	int		error;	ASSERT(agno != NULLAGNUMBER);	ASSERT(agbno != NULLAGBLOCK);	d = XFS_AGB_TO_DADDR(mp, agno, agbno);	if ((error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, d,					mp->m_bsize, lock, &bp))) {		return error;	}	ASSERT(!bp || !XFS_BUF_GETERROR(bp));	if (bp != NULL) {		switch (refval) {		case XFS_ALLOC_BTREE_REF:			XFS_BUF_SET_VTYPE_REF(bp, B_FS_MAP, refval);			break;		case XFS_INO_BTREE_REF:			XFS_BUF_SET_VTYPE_REF(bp, B_FS_INOMAP, refval);			break;		}	}	*bpp = bp;	return 0;}/* * Read-ahead the block, don't wait for it, don't return a buffer. * Long-form addressing. *//* ARGSUSED */voidxfs_btree_reada_bufl(	xfs_mount_t	*mp,		/* file system mount point */	xfs_fsblock_t	fsbno,		/* file system block number */	xfs_extlen_t	count)		/* count of filesystem blocks */{	xfs_daddr_t		d;	ASSERT(fsbno != NULLFSBLOCK);	d = XFS_FSB_TO_DADDR(mp, fsbno);	xfs_baread(mp->m_ddev_targp, d, mp->m_bsize * count);}/* * Read-ahead the block, don't wait for it, don't return a buffer. * Short-form addressing. *//* ARGSUSED */voidxfs_btree_reada_bufs(	xfs_mount_t	*mp,		/* file system mount point */	xfs_agnumber_t	agno,		/* allocation group number */	xfs_agblock_t	agbno,		/* allocation group block number */	xfs_extlen_t	count)		/* count of filesystem blocks */{	xfs_daddr_t		d;	ASSERT(agno != NULLAGNUMBER);	ASSERT(agbno != NULLAGBLOCK);	d = XFS_AGB_TO_DADDR(mp, agno, agbno);	xfs_baread(mp->m_ddev_targp, d, mp->m_bsize * count);}/* * Read-ahead btree blocks, at the given level. * Bits in lr are set from XFS_BTCUR_{LEFT,RIGHT}RA. */intxfs_btree_readahead_core(	xfs_btree_cur_t		*cur,		/* btree cursor */	int			lev,		/* level in btree */	int			lr)		/* left/right bits */{	xfs_alloc_block_t	*a;	xfs_bmbt_block_t	*b;	xfs_inobt_block_t	*i;	int			rval = 0;	ASSERT(cur->bc_bufs[lev] != NULL);	cur->bc_ra[lev] |= lr;	switch (cur->bc_btnum) {	case XFS_BTNUM_BNO:	case XFS_BTNUM_CNT:		a = XFS_BUF_TO_ALLOC_BLOCK(cur->bc_bufs[lev]);		if ((lr & XFS_BTCUR_LEFTRA) && be32_to_cpu(a->bb_leftsib) != NULLAGBLOCK) {			xfs_btree_reada_bufs(cur->bc_mp, cur->bc_private.a.agno,				be32_to_cpu(a->bb_leftsib), 1);			rval++;		}		if ((lr & XFS_BTCUR_RIGHTRA) && be32_to_cpu(a->bb_rightsib) != NULLAGBLOCK) {			xfs_btree_reada_bufs(cur->bc_mp, cur->bc_private.a.agno,				be32_to_cpu(a->bb_rightsib), 1);			rval++;		}		break;	case XFS_BTNUM_BMAP:		b = XFS_BUF_TO_BMBT_BLOCK(cur->bc_bufs[lev]);		if ((lr & XFS_BTCUR_LEFTRA) && be64_to_cpu(b->bb_leftsib) != NULLDFSBNO) {			xfs_btree_reada_bufl(cur->bc_mp, be64_to_cpu(b->bb_leftsib), 1);			rval++;		}		if ((lr & XFS_BTCUR_RIGHTRA) && be64_to_cpu(b->bb_rightsib) != NULLDFSBNO) {			xfs_btree_reada_bufl(cur->bc_mp, be64_to_cpu(b->bb_rightsib), 1);			rval++;		}		break;	case XFS_BTNUM_INO:		i = XFS_BUF_TO_INOBT_BLOCK(cur->bc_bufs[lev]);		if ((lr & XFS_BTCUR_LEFTRA) && be32_to_cpu(i->bb_leftsib) != NULLAGBLOCK) {			xfs_btree_reada_bufs(cur->bc_mp, cur->bc_private.i.agno,				be32_to_cpu(i->bb_leftsib), 1);			rval++;		}		if ((lr & XFS_BTCUR_RIGHTRA) && be32_to_cpu(i->bb_rightsib) != NULLAGBLOCK) {			xfs_btree_reada_bufs(cur->bc_mp, cur->bc_private.i.agno,				be32_to_cpu(i->bb_rightsib), 1);			rval++;		}		break;	default:		ASSERT(0);	}	return rval;}/* * Set the buffer for level "lev" in the cursor to bp, releasing * any previous buffer. */voidxfs_btree_setbuf(	xfs_btree_cur_t		*cur,	/* btree cursor */	int			lev,	/* level in btree */	xfs_buf_t		*bp)	/* new buffer to set */{	xfs_btree_block_t	*b;	/* btree block */	xfs_buf_t		*obp;	/* old buffer pointer */	obp = cur->bc_bufs[lev];	if (obp)		xfs_trans_brelse(cur->bc_tp, obp);	cur->bc_bufs[lev] = bp;	cur->bc_ra[lev] = 0;	if (!bp)		return;	b = XFS_BUF_TO_BLOCK(bp);	if (XFS_BTREE_LONG_PTRS(cur->bc_btnum)) {		if (be64_to_cpu(b->bb_u.l.bb_leftsib) == NULLDFSBNO)			cur->bc_ra[lev] |= XFS_BTCUR_LEFTRA;		if (be64_to_cpu(b->bb_u.l.bb_rightsib) == NULLDFSBNO)			cur->bc_ra[lev] |= XFS_BTCUR_RIGHTRA;	} else {		if (be32_to_cpu(b->bb_u.s.bb_leftsib) == NULLAGBLOCK)			cur->bc_ra[lev] |= XFS_BTCUR_LEFTRA;		if (be32_to_cpu(b->bb_u.s.bb_rightsib) == NULLAGBLOCK)			cur->bc_ra[lev] |= XFS_BTCUR_RIGHTRA;	}}

⌨️ 快捷键说明

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