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

📄 xfs_alloc_btree.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
#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 (be32_to_cpu(block->bb_leftsib) == 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 = be32_to_cpu(*XFS_ALLOC_PTR_ADDR(block, cur->bc_ptrs[lev], cur));		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] = be16_to_cpu(block->bb_numrecs);	}	*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 > be16_to_cpu(block->bb_numrecs) || 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 = be32_to_cpu(rec->ar_startblock);		*len = be32_to_cpu(rec->ar_blockcount);	}	*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] <= be16_to_cpu(block->bb_numrecs)) {		*stat = 1;		return 0;	}	/*	 * If we just went off the right edge of the tree, return failure.	 */	if (be32_to_cpu(block->bb_rightsib) == 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] <= be16_to_cpu(block->bb_numrecs))			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 = be32_to_cpu(*XFS_ALLOC_PTR_ADDR(block, cur->bc_ptrs[lev], cur));		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;	nrec.ar_startblock = cpu_to_be32(cur->bc_rec.a.ar_startblock);	nrec.ar_blockcount = cpu_to_be32(cur->bc_rec.a.ar_blockcount);	ncur = NULL;	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 caller's cursor, but otherwise we should		 * if ncur is a new cursor or we're about to be done.		 */		if (pcur != cur && (ncur || nbno == NULLAGBLOCK)) {			cur->bc_nlevels = pcur->bc_nlevels;			xfs_btree_del_cursor(pcur, XFS_BTREE_NOERROR);		}		/*		 * If we got a new cursor, switch to it.		 */		if (ncur) {			pcur = ncur;			ncur = NULL;		}	} while (nbno != NULLAGBLOCK);	*stat = i;	return 0;}/* * Lookup the record equal to [bno, len] in the btree given by cur. */int					/* error */xfs_alloc_lookup_eq(	xfs_btree_cur_t	*cur,		/* btree cursor */	xfs_agblock_t	bno,		/* starting block of extent */	xfs_extlen_t	len,		/* length of extent */	int		*stat)		/* success/failure */{	cur->bc_rec.a.ar_startblock = bno;	cur->bc_rec.a.ar_blockcount = len;	return xfs_alloc_lookup(cur, XFS_LOOKUP_EQ, stat);}/* * Lookup the first record greater than or equal to [bno, len] * in the btree given by cur. */int					/* error */xfs_alloc_lookup_ge(	xfs_btree_cur_t	*cur,		/* btree cursor */	xfs_agblock_t	bno,		/* starting block of extent */	xfs_extlen_t	len,		/* length of extent */	int		*stat)		/* success/failure */{	cur->bc_rec.a.ar_startblock = bno;	cur->bc_rec.a.ar_blockcount = len;	return xfs_alloc_lookup(cur, XFS_LOOKUP_GE, stat);}/* * Lookup the first record less than or equal to [bno, len] * in the btree given by cur. */int					/* error */xfs_alloc_lookup_le(	xfs_btree_cur_t	*cur,		/* btree cursor */	xfs_agblock_t	bno,		/* starting block of extent */	xfs_extlen_t	len,		/* length of extent */	int		*stat)		/* success/failure */{	cur->bc_rec.a.ar_startblock = bno;	cur->bc_rec.a.ar_blockcount = len;	return xfs_alloc_lookup(cur, XFS_LOOKUP_LE, stat);}/* * Update the record referred to by cur, to the value given by [bno, len]. * This either works (return 0) or gets an EFSCORRUPTED error. */int					/* error */xfs_alloc_update(	xfs_btree_cur_t		*cur,	/* btree cursor */	xfs_agblock_t		bno,	/* starting block of extent */	xfs_extlen_t		len)	/* length of extent */{	xfs_alloc_block_t	*block;	/* btree block to update */	int			error;	/* error return value */	int			ptr;	/* current record number (updating) */	ASSERT(len > 0);	/*	 * Pick up the a.g. freelist struct and the current block.	 */	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	/*	 * Get the address of the rec to be updated.	 */	ptr = cur->bc_ptrs[0];	{		xfs_alloc_rec_t		*rp;	/* pointer to updated record */		rp = XFS_ALLOC_REC_ADDR(block, ptr, cur);		/*		 * Fill in the new contents and log them.		 */		rp->ar_startblock = cpu_to_be32(bno);		rp->ar_blockcount = cpu_to_be32(len);		xfs_alloc_log_recs(cur, cur->bc_bufs[0], ptr, ptr);	}	/*	 * If it's the by-size btree and it's the last leaf block and	 * it's the last record... then update the size of the longest	 * extent in the a.g., which we cache in the a.g. freelist header.	 */	if (cur->bc_btnum == XFS_BTNUM_CNT &&	    be32_to_cpu(block->bb_rightsib) == NULLAGBLOCK &&	    ptr == be16_to_cpu(block->bb_numrecs)) {		xfs_agf_t	*agf;	/* a.g. freespace header */		xfs_agnumber_t	seqno;		agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp);		seqno = be32_to_cpu(agf->agf_seqno);		cur->bc_mp->m_perag[seqno].pagf_longest = len;		agf->agf_longest = cpu_to_be32(len);		xfs_alloc_log_agf(cur->bc_tp, cur->bc_private.a.agbp,			XFS_AGF_LONGEST);	}	/*	 * Updating first record in leaf. Pass new key value up to our parent.	 */	if (ptr == 1) {		xfs_alloc_key_t	key;	/* key containing [bno, len] */		key.ar_startblock = cpu_to_be32(bno);		key.ar_blockcount = cpu_to_be32(len);		if ((error = xfs_alloc_updkey(cur, &key, 1)))			return error;	

⌨️ 快捷键说明

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