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

📄 xfs_bmap_btree.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		XFS_BMBT_TRACE_CURSOR(tcur, ERROR);		goto error1;	}	xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR);	XFS_BMBT_TRACE_CURSOR(cur, EXIT);	*stat = 1;	return 0;error0:	XFS_BMBT_TRACE_CURSOR(cur, ERROR);error1:	xfs_btree_del_cursor(tcur, XFS_BTREE_ERROR);	return error;}/* * Determine the extent state. *//* ARGSUSED */STATIC xfs_exntst_txfs_extent_state(	xfs_filblks_t		blks,	int			extent_flag){	if (extent_flag) {		ASSERT(blks != 0);	/* saved for DMIG */		return XFS_EXT_UNWRITTEN;	}	return XFS_EXT_NORM;}/* * Split cur/level block in half. * Return new block number and its first record (to be inserted into parent). */STATIC int					/* error */xfs_bmbt_split(	xfs_btree_cur_t		*cur,	int			level,	xfs_fsblock_t		*bnop,	__uint64_t		*startoff,	xfs_btree_cur_t		**curp,	int			*stat)		/* success/failure */{	xfs_alloc_arg_t		args;		/* block allocation args */	int			error;		/* error return value */	int			i;		/* loop counter */	xfs_fsblock_t		lbno;		/* left sibling block number */	xfs_buf_t		*lbp;		/* left buffer pointer */	xfs_bmbt_block_t	*left;		/* left btree block */	xfs_bmbt_key_t		*lkp;		/* left btree key */	xfs_bmbt_ptr_t		*lpp;		/* left address pointer */	xfs_bmbt_rec_t		*lrp;		/* left record pointer */	xfs_buf_t		*rbp;		/* right buffer pointer */	xfs_bmbt_block_t	*right;		/* right btree block */	xfs_bmbt_key_t		*rkp;		/* right btree key */	xfs_bmbt_ptr_t		*rpp;		/* right address pointer */	xfs_bmbt_block_t	*rrblock;	/* right-right btree block */	xfs_buf_t		*rrbp;		/* right-right buffer pointer */	xfs_bmbt_rec_t		*rrp;		/* right record pointer */	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);	XFS_BMBT_TRACE_ARGIFK(cur, level, *bnop, *startoff);	args.tp = cur->bc_tp;	args.mp = cur->bc_mp;	lbp = cur->bc_bufs[level];	lbno = XFS_DADDR_TO_FSB(args.mp, XFS_BUF_ADDR(lbp));	left = XFS_BUF_TO_BMBT_BLOCK(lbp);	args.fsbno = cur->bc_private.b.firstblock;	args.firstblock = args.fsbno;	if (args.fsbno == NULLFSBLOCK) {		args.fsbno = lbno;		args.type = XFS_ALLOCTYPE_START_BNO;	} else		args.type = XFS_ALLOCTYPE_NEAR_BNO;	args.mod = args.minleft = args.alignment = args.total = args.isfl =		args.userdata = args.minalignslop = 0;	args.minlen = args.maxlen = args.prod = 1;	args.wasdel = cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL;	if (!args.wasdel && xfs_trans_get_block_res(args.tp) == 0) {		XFS_BMBT_TRACE_CURSOR(cur, ERROR);		return XFS_ERROR(ENOSPC);	}	if ((error = xfs_alloc_vextent(&args))) {		XFS_BMBT_TRACE_CURSOR(cur, ERROR);		return error;	}	if (args.fsbno == NULLFSBLOCK) {		XFS_BMBT_TRACE_CURSOR(cur, EXIT);		*stat = 0;		return 0;	}	ASSERT(args.len == 1);	cur->bc_private.b.firstblock = args.fsbno;	cur->bc_private.b.allocated++;	cur->bc_private.b.ip->i_d.di_nblocks++;	xfs_trans_log_inode(args.tp, cur->bc_private.b.ip, XFS_ILOG_CORE);	XFS_TRANS_MOD_DQUOT_BYINO(args.mp, args.tp, cur->bc_private.b.ip,			XFS_TRANS_DQ_BCOUNT, 1L);	rbp = xfs_btree_get_bufl(args.mp, args.tp, args.fsbno, 0);	right = XFS_BUF_TO_BMBT_BLOCK(rbp);#ifdef DEBUG	if ((error = xfs_btree_check_lblock(cur, left, level, rbp))) {		XFS_BMBT_TRACE_CURSOR(cur, ERROR);		return error;	}#endif	right->bb_magic = cpu_to_be32(XFS_BMAP_MAGIC);	right->bb_level = left->bb_level;	right->bb_numrecs = cpu_to_be16(be16_to_cpu(left->bb_numrecs) / 2);	if ((be16_to_cpu(left->bb_numrecs) & 1) &&	    cur->bc_ptrs[level] <= be16_to_cpu(right->bb_numrecs) + 1)		be16_add(&right->bb_numrecs, 1);	i = be16_to_cpu(left->bb_numrecs) - be16_to_cpu(right->bb_numrecs) + 1;	if (level > 0) {		lkp = XFS_BMAP_KEY_IADDR(left, i, cur);		lpp = XFS_BMAP_PTR_IADDR(left, i, cur);		rkp = XFS_BMAP_KEY_IADDR(right, 1, cur);		rpp = XFS_BMAP_PTR_IADDR(right, 1, cur);#ifdef DEBUG		for (i = 0; i < be16_to_cpu(right->bb_numrecs); i++) {			if ((error = xfs_btree_check_lptr_disk(cur, lpp[i], level))) {				XFS_BMBT_TRACE_CURSOR(cur, ERROR);				return error;			}		}#endif		memcpy(rkp, lkp, be16_to_cpu(right->bb_numrecs) * sizeof(*rkp));		memcpy(rpp, lpp, be16_to_cpu(right->bb_numrecs) * sizeof(*rpp));		xfs_bmbt_log_keys(cur, rbp, 1, be16_to_cpu(right->bb_numrecs));		xfs_bmbt_log_ptrs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs));		*startoff = be64_to_cpu(rkp->br_startoff);	} else {		lrp = XFS_BMAP_REC_IADDR(left, i, cur);		rrp = XFS_BMAP_REC_IADDR(right, 1, cur);		memcpy(rrp, lrp, be16_to_cpu(right->bb_numrecs) * sizeof(*rrp));		xfs_bmbt_log_recs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs));		*startoff = xfs_bmbt_disk_get_startoff(rrp);	}	be16_add(&left->bb_numrecs, -(be16_to_cpu(right->bb_numrecs)));	right->bb_rightsib = left->bb_rightsib;	left->bb_rightsib = cpu_to_be64(args.fsbno);	right->bb_leftsib = cpu_to_be64(lbno);	xfs_bmbt_log_block(cur, rbp, XFS_BB_ALL_BITS);	xfs_bmbt_log_block(cur, lbp, XFS_BB_NUMRECS | XFS_BB_RIGHTSIB);	if (be64_to_cpu(right->bb_rightsib) != NULLDFSBNO) {		if ((error = xfs_btree_read_bufl(args.mp, args.tp,				be64_to_cpu(right->bb_rightsib), 0, &rrbp,				XFS_BMAP_BTREE_REF))) {			XFS_BMBT_TRACE_CURSOR(cur, ERROR);			return error;		}		rrblock = XFS_BUF_TO_BMBT_BLOCK(rrbp);		if ((error = xfs_btree_check_lblock(cur, rrblock, level, rrbp))) {			XFS_BMBT_TRACE_CURSOR(cur, ERROR);			return error;		}		rrblock->bb_leftsib = cpu_to_be64(args.fsbno);		xfs_bmbt_log_block(cur, rrbp, XFS_BB_LEFTSIB);	}	if (cur->bc_ptrs[level] > be16_to_cpu(left->bb_numrecs) + 1) {		xfs_btree_setbuf(cur, level, rbp);		cur->bc_ptrs[level] -= be16_to_cpu(left->bb_numrecs);	}	if (level + 1 < cur->bc_nlevels) {		if ((error = xfs_btree_dup_cursor(cur, curp))) {			XFS_BMBT_TRACE_CURSOR(cur, ERROR);			return error;		}		(*curp)->bc_ptrs[level + 1]++;	}	*bnop = args.fsbno;	XFS_BMBT_TRACE_CURSOR(cur, EXIT);	*stat = 1;	return 0;}/* * Update keys for the record. */STATIC intxfs_bmbt_updkey(	xfs_btree_cur_t		*cur,	xfs_bmbt_key_t		*keyp,	/* on-disk format */	int			level){	xfs_bmbt_block_t	*block;	xfs_buf_t		*bp;#ifdef DEBUG	int			error;#endif	xfs_bmbt_key_t		*kp;	int			ptr;	ASSERT(level >= 1);	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);	XFS_BMBT_TRACE_ARGIK(cur, level, keyp);	for (ptr = 1; ptr == 1 && level < cur->bc_nlevels; level++) {		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];		kp = XFS_BMAP_KEY_IADDR(block, ptr, cur);		*kp = *keyp;		xfs_bmbt_log_keys(cur, bp, ptr, ptr);	}	XFS_BMBT_TRACE_CURSOR(cur, EXIT);	return 0;}/* * Convert on-disk form of btree root to in-memory form. */voidxfs_bmdr_to_bmbt(	xfs_bmdr_block_t	*dblock,	int			dblocklen,	xfs_bmbt_block_t	*rblock,	int			rblocklen){	int			dmxr;	xfs_bmbt_key_t		*fkp;	__be64			*fpp;	xfs_bmbt_key_t		*tkp;	__be64			*tpp;	rblock->bb_magic = cpu_to_be32(XFS_BMAP_MAGIC);	rblock->bb_level = dblock->bb_level;	ASSERT(be16_to_cpu(rblock->bb_level) > 0);	rblock->bb_numrecs = dblock->bb_numrecs;	rblock->bb_leftsib = cpu_to_be64(NULLDFSBNO);	rblock->bb_rightsib = cpu_to_be64(NULLDFSBNO);	dmxr = (int)XFS_BTREE_BLOCK_MAXRECS(dblocklen, xfs_bmdr, 0);	fkp = XFS_BTREE_KEY_ADDR(xfs_bmdr, dblock, 1);	tkp = XFS_BMAP_BROOT_KEY_ADDR(rblock, 1, rblocklen);	fpp = XFS_BTREE_PTR_ADDR(xfs_bmdr, dblock, 1, dmxr);	tpp = XFS_BMAP_BROOT_PTR_ADDR(rblock, 1, rblocklen);	dmxr = be16_to_cpu(dblock->bb_numrecs);	memcpy(tkp, fkp, sizeof(*fkp) * dmxr);	memcpy(tpp, fpp, sizeof(*fpp) * dmxr);}/* * Decrement cursor by one record at the level. * For nonzero levels the leaf-ward information is untouched. */int						/* error */xfs_bmbt_decrement(	xfs_btree_cur_t		*cur,	int			level,	int			*stat)		/* success/failure */{	xfs_bmbt_block_t	*block;	xfs_buf_t		*bp;	int			error;		/* error return value */	xfs_fsblock_t		fsbno;	int			lev;	xfs_mount_t		*mp;	xfs_trans_t		*tp;	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);	XFS_BMBT_TRACE_ARGI(cur, level);	ASSERT(level < cur->bc_nlevels);	if (level < cur->bc_nlevels - 1)		xfs_btree_readahead(cur, level, XFS_BTCUR_LEFTRA);	if (--cur->bc_ptrs[level] > 0) {		XFS_BMBT_TRACE_CURSOR(cur, EXIT);		*stat = 1;		return 0;	}	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	if (be64_to_cpu(block->bb_leftsib) == NULLDFSBNO) {		XFS_BMBT_TRACE_CURSOR(cur, EXIT);		*stat = 0;		return 0;	}	for (lev = level + 1; lev < cur->bc_nlevels; lev++) {		if (--cur->bc_ptrs[lev] > 0)			break;		if (lev < cur->bc_nlevels - 1)			xfs_btree_readahead(cur, lev, XFS_BTCUR_LEFTRA);	}	if (lev == cur->bc_nlevels) {		XFS_BMBT_TRACE_CURSOR(cur, EXIT);		*stat = 0;		return 0;	}	tp = cur->bc_tp;	mp = cur->bc_mp;	for (block = xfs_bmbt_get_block(cur, lev, &bp); lev > level; ) {		fsbno = be64_to_cpu(*XFS_BMAP_PTR_IADDR(block, cur->bc_ptrs[lev], cur));		if ((error = xfs_btree_read_bufl(mp, tp, fsbno, 0, &bp,				XFS_BMAP_BTREE_REF))) {			XFS_BMBT_TRACE_CURSOR(cur, ERROR);			return error;		}		lev--;		xfs_btree_setbuf(cur, lev, bp);		block = XFS_BUF_TO_BMBT_BLOCK(bp);		if ((error = xfs_btree_check_lblock(cur, block, lev, bp))) {			XFS_BMBT_TRACE_CURSOR(cur, ERROR);			return error;		}		cur->bc_ptrs[lev] = be16_to_cpu(block->bb_numrecs);	}	XFS_BMBT_TRACE_CURSOR(cur, EXIT);	*stat = 1;	return 0;}/* * Delete the record pointed to by cur. */int					/* error */xfs_bmbt_delete(	xfs_btree_cur_t	*cur,	int		*stat)		/* success/failure */{	int		error;		/* error return value */	int		i;	int		level;	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);	for (level = 0, i = 2; i == 2; level++) {		if ((error = xfs_bmbt_delrec(cur, level, &i))) {			XFS_BMBT_TRACE_CURSOR(cur, ERROR);			return error;		}	}	if (i == 0) {		for (level = 1; level < cur->bc_nlevels; level++) {			if (cur->bc_ptrs[level] == 0) {				if ((error = xfs_bmbt_decrement(cur, level,						&i))) {					XFS_BMBT_TRACE_CURSOR(cur, ERROR);					return error;				}				break;			}		}	}	XFS_BMBT_TRACE_CURSOR(cur, EXIT);	*stat = i;	return 0;}/* * Convert a compressed bmap extent record to an uncompressed form. * This code must be in sync with the routines xfs_bmbt_get_startoff, * xfs_bmbt_get_startblock, xfs_bmbt_get_blockcount and xfs_bmbt_get_state. */STATIC_INLINE void__xfs_bmbt_get_all(		__uint64_t l0,		__uint64_t l1,		xfs_bmbt_irec_t *s){	int	ext_flag;	xfs_exntst_t st;	ext_flag = (int)(l0 >> (64 - BMBT_EXNTFLAG_BITLEN));	s->br_startoff = ((xfs_fileoff_t)l0 &			   XFS_MASK64LO(64 - BMBT_EXNTFLAG_BITLEN)) >> 9;#if XFS_BIG_BLKNOS	s->br_startblock = (((xfs_fsblock_t)l0 & XFS_MASK64LO(9)) << 43) |			   (((xfs_fsblock_t)l1) >> 21);#else#ifdef DEBUG	{		xfs_dfsbno_t	b;		b = (((xfs_dfsbno_t)l0 & XFS_MASK64LO(9)) << 43) |		    (((xfs_dfsbno_t)l1) >> 21);		ASSERT((b >> 32) == 0 || ISNULLDSTARTBLOCK(b));		s->br_startblock = (xfs_fsblock_t)b;	}#else	/* !DEBUG */	s->br_startblock = (xfs_fsblock_t)(((xfs_dfsbno_t)l1) >> 21);#endif	/* DEBUG */#endif	/* XFS_BIG_BLKNOS */	s->br_blockcount = (xfs_filblks_t)(l1 & XFS_MASK64LO(21));	/* This is xfs_extent_state() in-line */	if (ext_flag) {		ASSERT(s->br_blockcount != 0);	/* saved for DMIG */		st = XFS_EXT_UNWRITTEN;	} else		st = XFS_EXT_NORM;	s->br_state = st;}voidxfs_bmbt_get_all(	xfs_bmbt_rec_host_t *r,	xfs_bmbt_irec_t *s){	__xfs_bmbt_get_all(r->l0, r->l1, s);}/* * Get the block pointer for the given level of the cursor. * Fill in the buffer pointer, if applicable. */xfs_bmbt_block_t *xfs_bmbt_get_block(	xfs_btree_cur_t		*cur,	int			level,	xfs_buf_t		**bpp){	xfs_ifork_t		*ifp;	xfs_bmbt_block_t	*rval;	if (level < cur->bc_nlevels - 1) {		*bpp = cur->bc_bufs[level];		rval = XFS_BUF_TO_BMBT_BLOCK(*bpp);	} else {		*bpp = NULL;		ifp = XFS_IFORK_PTR(cur->bc_private.b.ip,			cur->bc_private.b.whichfork);		rval = ifp->if_broot;	}	return rval;}/* * Extract the blockcount field from an in memory bmap extent record. */xfs_filblks_txfs_bmbt_get_blockcount(	xfs_bmbt_rec_host_t	*r){	return (xfs_filblks_t)(r->l1 & XFS_MASK64LO(21));}/* * Extract the startblock field from an in memory bmap extent record. */xfs_fsblock_txfs_bmbt_get_startblock(	xfs_bmbt_rec_host_t	*r){#if XFS_BIG_BLKNOS	return (((xfs_fsblock_t)r->l0 & XFS_MASK64LO(9)) << 43) |	       (((xfs_fsblock_t)r->l1) >> 21);#else#ifdef DEBUG	xfs_dfsbno_t	b;	b = (((xfs_dfsbno_t)r->l0 & XFS_MASK64LO(9)) << 43) |	    (((xfs_dfsbno_t)r->l1) >> 21);	ASSERT((b >> 32) == 0 || ISNULLDSTARTBLOCK(b));	return (xfs_fsblock_t)b;#else	/* !DEBUG */	return (xfs_fsblock_t)(((xfs_dfsbno_t)r->l1) >> 21);#endif	/* DEBUG */#endif	/* XFS_BIG_BLKNOS */}/* * Extract the startoff field from an in memory bmap extent record. */xfs_fileoff_txfs_bmbt_get_startoff(	xfs_bmbt_rec_host_t	*r)

⌨️ 快捷键说明

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