Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 637aa50f authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Lachlan McIlroy
Browse files

[XFS] implement generic xfs_btree_increment



From: Dave Chinner <dgc@sgi.com>

Because this is the first major generic btree routine this patch includes
some infrastrucure, first a few routines to deal with a btree block that
can be either in short or long form, second xfs_btree_read_buf_block,
which is the new central routine to read a btree block given a cursor, and
third the new xfs_btree_ptr_addr routine to calculate the address for a
given btree pointer record.

[hch: split out from bigger patch and minor adaptions]

SGI-PV: 985583

SGI-Modid: xfs-linux-melb:xfs-kern:32190a

Signed-off-by: default avatarChristoph Hellwig <hch@infradead.org>
Signed-off-by: default avatarLachlan McIlroy <lachlan@sgi.com>
Signed-off-by: default avatarBill O'Donnell <billodo@sgi.com>
Signed-off-by: default avatarDavid Chinner <david@fromorbit.com>
parent 65f1eaea
Loading
Loading
Loading
Loading
+6 −6
Original line number Original line Diff line number Diff line
@@ -818,7 +818,7 @@ xfs_alloc_ag_vextent_near(
				XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
				XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
				if (ltlen >= args->minlen)
				if (ltlen >= args->minlen)
					break;
					break;
				if ((error = xfs_alloc_increment(cnt_cur, 0, &i)))
				if ((error = xfs_btree_increment(cnt_cur, 0, &i)))
					goto error0;
					goto error0;
			} while (i);
			} while (i);
			ASSERT(ltlen >= args->minlen);
			ASSERT(ltlen >= args->minlen);
@@ -828,7 +828,7 @@ xfs_alloc_ag_vextent_near(
		i = cnt_cur->bc_ptrs[0];
		i = cnt_cur->bc_ptrs[0];
		for (j = 1, blen = 0, bdiff = 0;
		for (j = 1, blen = 0, bdiff = 0;
		     !error && j && (blen < args->maxlen || bdiff > 0);
		     !error && j && (blen < args->maxlen || bdiff > 0);
		     error = xfs_alloc_increment(cnt_cur, 0, &j)) {
		     error = xfs_btree_increment(cnt_cur, 0, &j)) {
			/*
			/*
			 * For each entry, decide if it's better than
			 * For each entry, decide if it's better than
			 * the previous best entry.
			 * the previous best entry.
@@ -938,7 +938,7 @@ xfs_alloc_ag_vextent_near(
	 * Increment the cursor, so we will point at the entry just right
	 * Increment the cursor, so we will point at the entry just right
	 * of the leftward entry if any, or to the leftmost entry.
	 * of the leftward entry if any, or to the leftmost entry.
	 */
	 */
	if ((error = xfs_alloc_increment(bno_cur_gt, 0, &i)))
	if ((error = xfs_btree_increment(bno_cur_gt, 0, &i)))
		goto error0;
		goto error0;
	if (!i) {
	if (!i) {
		/*
		/*
@@ -977,7 +977,7 @@ xfs_alloc_ag_vextent_near(
					args->minlen, &gtbnoa, &gtlena);
					args->minlen, &gtbnoa, &gtlena);
			if (gtlena >= args->minlen)
			if (gtlena >= args->minlen)
				break;
				break;
			if ((error = xfs_alloc_increment(bno_cur_gt, 0, &i)))
			if ((error = xfs_btree_increment(bno_cur_gt, 0, &i)))
				goto error0;
				goto error0;
			if (!i) {
			if (!i) {
				xfs_btree_del_cursor(bno_cur_gt,
				xfs_btree_del_cursor(bno_cur_gt,
@@ -1066,7 +1066,7 @@ xfs_alloc_ag_vextent_near(
					/*
					/*
					 * Fell off the right end.
					 * Fell off the right end.
					 */
					 */
					if ((error = xfs_alloc_increment(
					if ((error = xfs_btree_increment(
							bno_cur_gt, 0, &i)))
							bno_cur_gt, 0, &i)))
						goto error0;
						goto error0;
					if (!i) {
					if (!i) {
@@ -1548,7 +1548,7 @@ xfs_free_ag_extent(
	 * Look for a neighboring block on the right (higher block numbers)
	 * Look for a neighboring block on the right (higher block numbers)
	 * that is contiguous with this space.
	 * that is contiguous with this space.
	 */
	 */
	if ((error = xfs_alloc_increment(bno_cur, 0, &haveright)))
	if ((error = xfs_btree_increment(bno_cur, 0, &haveright)))
		goto error0;
		goto error0;
	if (haveright) {
	if (haveright) {
		/*
		/*
+4 −95
Original line number Original line Diff line number Diff line
@@ -303,7 +303,7 @@ xfs_alloc_delrec(
		 */
		 */
		i = xfs_btree_lastrec(tcur, level);
		i = xfs_btree_lastrec(tcur, level);
		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
		if ((error = xfs_alloc_increment(tcur, level, &i)))
		if ((error = xfs_btree_increment(tcur, level, &i)))
			goto error0;
			goto error0;
		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
		i = xfs_btree_lastrec(tcur, level);
		i = xfs_btree_lastrec(tcur, level);
@@ -517,7 +517,7 @@ xfs_alloc_delrec(
	 * us, increment the cursor at that level.
	 * us, increment the cursor at that level.
	 */
	 */
	else if (level + 1 < cur->bc_nlevels &&
	else if (level + 1 < cur->bc_nlevels &&
		 (error = xfs_alloc_increment(cur, level + 1, &i)))
		 (error = xfs_btree_increment(cur, level + 1, &i)))
		return error;
		return error;
	/*
	/*
	 * Fix up the number of records in the surviving block.
	 * Fix up the number of records in the surviving block.
@@ -1134,7 +1134,7 @@ xfs_alloc_lookup(
			int	i;
			int	i;


			cur->bc_ptrs[0] = keyno;
			cur->bc_ptrs[0] = keyno;
			if ((error = xfs_alloc_increment(cur, 0, &i)))
			if ((error = xfs_btree_increment(cur, 0, &i)))
				return error;
				return error;
			XFS_WANT_CORRUPTED_RETURN(i == 1);
			XFS_WANT_CORRUPTED_RETURN(i == 1);
			*stat = 1;
			*stat = 1;
@@ -1570,7 +1570,7 @@ xfs_alloc_rshift(
		return error;
		return error;
	i = xfs_btree_lastrec(tcur, level);
	i = xfs_btree_lastrec(tcur, level);
	XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
	XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
	if ((error = xfs_alloc_increment(tcur, level, &i)) ||
	if ((error = xfs_btree_increment(tcur, level, &i)) ||
	    (error = xfs_alloc_updkey(tcur, rkp, level + 1)))
	    (error = xfs_alloc_updkey(tcur, rkp, level + 1)))
		goto error0;
		goto error0;
	xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR);
	xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR);
@@ -1942,97 +1942,6 @@ xfs_alloc_get_rec(
	return 0;
	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.
 * Insert the current record at the point referenced by cur.
 * The cursor may be inconsistent on return if splits have been done.
 * The cursor may be inconsistent on return if splits have been done.
+0 −6
Original line number Original line Diff line number Diff line
@@ -113,12 +113,6 @@ extern int xfs_alloc_delete(struct xfs_btree_cur *cur, int *stat);
extern int xfs_alloc_get_rec(struct xfs_btree_cur *cur,	xfs_agblock_t *bno,
extern int xfs_alloc_get_rec(struct xfs_btree_cur *cur,	xfs_agblock_t *bno,
				xfs_extlen_t *len, int *stat);
				xfs_extlen_t *len, int *stat);


/*
 * Increment cursor by one record at the level.
 * For nonzero levels the leaf-ward information is untouched.
 */
extern int xfs_alloc_increment(struct xfs_btree_cur *cur, int level, int *stat);

/*
/*
 * Insert the current record at the point referenced by cur.
 * Insert the current record at the point referenced by cur.
 * The cursor may be inconsistent on return if splits have been done.
 * The cursor may be inconsistent on return if splits have been done.
+2 −2
Original line number Original line Diff line number Diff line
@@ -1646,7 +1646,7 @@ xfs_bmap_add_extent_unwritten_real(
				PREV.br_blockcount - new->br_blockcount,
				PREV.br_blockcount - new->br_blockcount,
				oldext)))
				oldext)))
				goto done;
				goto done;
			if ((error = xfs_bmbt_increment(cur, 0, &i)))
			if ((error = xfs_btree_increment(cur, 0, &i)))
				goto done;
				goto done;
			if ((error = xfs_bmbt_update(cur, new->br_startoff,
			if ((error = xfs_bmbt_update(cur, new->br_startoff,
				new->br_startblock,
				new->br_startblock,
@@ -3253,7 +3253,7 @@ xfs_bmap_del_extent(
						got.br_startblock, temp,
						got.br_startblock, temp,
						got.br_state)))
						got.br_state)))
					goto done;
					goto done;
				if ((error = xfs_bmbt_increment(cur, 0, &i)))
				if ((error = xfs_btree_increment(cur, 0, &i)))
					goto done;
					goto done;
				cur->bc_rec.b = new;
				cur->bc_rec.b = new;
				error = xfs_bmbt_insert(cur, &i);
				error = xfs_bmbt_insert(cur, &i);
+4 −84
Original line number Original line Diff line number Diff line
@@ -254,7 +254,7 @@ xfs_bmbt_delrec(
	if (rbno != NULLFSBLOCK) {
	if (rbno != NULLFSBLOCK) {
		i = xfs_btree_lastrec(tcur, level);
		i = xfs_btree_lastrec(tcur, level);
		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
		if ((error = xfs_bmbt_increment(tcur, level, &i))) {
		if ((error = xfs_btree_increment(tcur, level, &i))) {
			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
			goto error0;
			goto error0;
		}
		}
@@ -445,7 +445,7 @@ xfs_bmbt_delrec(
		cur->bc_bufs[level] = lbp;
		cur->bc_bufs[level] = lbp;
		cur->bc_ptrs[level] += lrecs;
		cur->bc_ptrs[level] += lrecs;
		cur->bc_ra[level] = 0;
		cur->bc_ra[level] = 0;
	} else if ((error = xfs_bmbt_increment(cur, level + 1, &i))) {
	} else if ((error = xfs_btree_increment(cur, level + 1, &i))) {
		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
		goto error0;
		goto error0;
	}
	}
@@ -929,7 +929,7 @@ xfs_bmbt_lookup(
		if (dir == XFS_LOOKUP_GE && keyno > be16_to_cpu(block->bb_numrecs) &&
		if (dir == XFS_LOOKUP_GE && keyno > be16_to_cpu(block->bb_numrecs) &&
		    be64_to_cpu(block->bb_rightsib) != NULLDFSBNO) {
		    be64_to_cpu(block->bb_rightsib) != NULLDFSBNO) {
			cur->bc_ptrs[0] = keyno;
			cur->bc_ptrs[0] = keyno;
			if ((error = xfs_bmbt_increment(cur, 0, &i))) {
			if ((error = xfs_btree_increment(cur, 0, &i))) {
				XFS_BMBT_TRACE_CURSOR(cur, ERROR);
				XFS_BMBT_TRACE_CURSOR(cur, ERROR);
				return error;
				return error;
			}
			}
@@ -1202,7 +1202,7 @@ xfs_bmbt_rshift(
	}
	}
	i = xfs_btree_lastrec(tcur, level);
	i = xfs_btree_lastrec(tcur, level);
	XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
	XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
	if ((error = xfs_bmbt_increment(tcur, level, &i))) {
	if ((error = xfs_btree_increment(tcur, level, &i))) {
		XFS_BMBT_TRACE_CURSOR(tcur, ERROR);
		XFS_BMBT_TRACE_CURSOR(tcur, ERROR);
		goto error1;
		goto error1;
	}
	}
@@ -1760,86 +1760,6 @@ xfs_bmbt_disk_get_startoff(
		 XFS_MASK64LO(64 - BMBT_EXNTFLAG_BITLEN)) >> 9;
		 XFS_MASK64LO(64 - BMBT_EXNTFLAG_BITLEN)) >> 9;
}
}


/*
 * Increment cursor by one record at the level.
 * For nonzero levels the leaf-ward information is untouched.
 */
int						/* error */
xfs_bmbt_increment(
	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);

	xfs_btree_readahead(cur, level, XFS_BTCUR_RIGHTRA);
	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 (++cur->bc_ptrs[level] <= be16_to_cpu(block->bb_numrecs)) {
		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
		*stat = 1;
		return 0;
	}
	if (be64_to_cpu(block->bb_rightsib) == NULLDFSBNO) {
		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
		*stat = 0;
		return 0;
	}
	for (lev = level + 1; lev < cur->bc_nlevels; lev++) {
		block = xfs_bmbt_get_block(cur, lev, &bp);
#ifdef DEBUG
		if ((error = xfs_btree_check_lblock(cur, block, lev, bp))) {
			XFS_BMBT_TRACE_CURSOR(cur, ERROR);
			return error;
		}
#endif
		if (++cur->bc_ptrs[lev] <= be16_to_cpu(block->bb_numrecs))
			break;
		xfs_btree_readahead(cur, lev, XFS_BTCUR_RIGHTRA);
	}
	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] = 1;
	}
	XFS_BMBT_TRACE_CURSOR(cur, EXIT);
	*stat = 1;
	return 0;
}

/*
/*
 * Insert the current record at the point referenced by cur.
 * Insert the current record at the point referenced by cur.
 *
 *
Loading