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

Commit 278d0ca1 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Lachlan McIlroy
Browse files

[XFS] implement generic xfs_btree_update



From: Dave Chinner <dgc@sgi.com>

The most complicated part here is the lastrec tracking for the alloc
btree. Most logic is in the update_lastrec method which has to do some
hopefully good enough dirty magic to maintain it.

[hch: split out from bigger patch and a rework of the lastrec

logic]

SGI-PV: 985583

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

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 38bb7423
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -136,6 +136,23 @@ xfs_alloc_lookup_le(
	return xfs_btree_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.
 */
STATIC int				/* error */
xfs_alloc_update(
	struct xfs_btree_cur	*cur,	/* btree cursor */
	xfs_agblock_t		bno,	/* starting block of extent */
	xfs_extlen_t		len)	/* length of extent */
{
	union xfs_btree_rec	rec;

	rec.alloc.ar_startblock = cpu_to_be32(bno);
	rec.alloc.ar_blockcount = cpu_to_be32(len);
	return xfs_btree_update(cur, &rec);
}

/*
 * Compute aligned version of the found extent.
+38 −68
Original line number Diff line number Diff line
@@ -1661,83 +1661,50 @@ xfs_alloc_insert(
	return 0;
}

/*
 * 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 */
STATIC struct xfs_btree_cur *
xfs_allocbt_dup_cursor(
	struct xfs_btree_cur	*cur)
{
	xfs_alloc_block_t	*block;	/* btree block to update */
	int			error;	/* error return value */
	int			ptr;	/* current record number (updating) */
	return xfs_allocbt_init_cursor(cur->bc_mp, cur->bc_tp,
			cur->bc_private.a.agbp, cur->bc_private.a.agno,
			cur->bc_btnum);
}

	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.
 * Update the longest extent in the AGF
 */
	ptr = cur->bc_ptrs[0];
STATIC void
xfs_allocbt_update_lastrec(
	struct xfs_btree_cur	*cur,
	struct xfs_btree_block	*block,
	union xfs_btree_rec	*rec,
	int			ptr,
	int			reason)
{
		xfs_alloc_rec_t		*rp;	/* pointer to updated record */
	struct xfs_agf		*agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp);
	xfs_agnumber_t		seqno = be32_to_cpu(agf->agf_seqno);
	__be32			len;

		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;
	ASSERT(cur->bc_btnum == XFS_BTNUM_CNT);

		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);
	}
	switch (reason) {
	case LASTREC_UPDATE:
		/*
	 * Updating first record in leaf. Pass new key value up to our parent.
		 * If this is the last leaf block and it's the last record,
		 * then update the size of the longest extent in the AG.
		 */
	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_btree_updkey(cur, (union xfs_btree_key *)&key, 1)))
			return error;
	}
	return 0;
		if (ptr != xfs_btree_get_numrecs(block))
			return;
		len = rec->alloc.ar_blockcount;
		break;
	default:
		ASSERT(0);
		return;
	}

STATIC struct xfs_btree_cur *
xfs_allocbt_dup_cursor(
	struct xfs_btree_cur	*cur)
{
	return xfs_allocbt_init_cursor(cur->bc_mp, cur->bc_tp,
			cur->bc_private.a.agbp, cur->bc_private.a.agno,
			cur->bc_btnum);
	agf->agf_longest = len;
	cur->bc_mp->m_perag[seqno].pagf_longest = be32_to_cpu(len);
	xfs_alloc_log_agf(cur->bc_tp, cur->bc_private.a.agbp, XFS_AGF_LONGEST);
}

STATIC int
@@ -1864,6 +1831,7 @@ static const struct xfs_btree_ops xfs_allocbt_ops = {
	.key_len		= sizeof(xfs_alloc_key_t),

	.dup_cursor		= xfs_allocbt_dup_cursor,
	.update_lastrec		= xfs_allocbt_update_lastrec,
	.get_maxrecs		= xfs_allocbt_get_maxrecs,
	.init_key_from_rec	= xfs_allocbt_init_key_from_rec,
	.init_ptr_from_cur	= xfs_allocbt_init_ptr_from_cur,
@@ -1902,6 +1870,8 @@ xfs_allocbt_init_cursor(
	cur->bc_blocklog = mp->m_sb.sb_blocklog;

	cur->bc_ops = &xfs_allocbt_ops;
	if (btnum == XFS_BTNUM_CNT)
		cur->bc_flags = XFS_BTREE_LASTREC_UPDATE;

	cur->bc_private.a.agbp = agbp;
	cur->bc_private.a.agno = agno;
+0 −7
Original line number Diff line number Diff line
@@ -113,13 +113,6 @@ extern int xfs_alloc_get_rec(struct xfs_btree_cur *cur, xfs_agblock_t *bno,
 */
extern int xfs_alloc_insert(struct xfs_btree_cur *cur, int *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.
 */
extern int xfs_alloc_update(struct xfs_btree_cur *cur, xfs_agblock_t bno,
				xfs_extlen_t len);


extern struct xfs_btree_cur *xfs_allocbt_init_cursor(struct xfs_mount *,
		struct xfs_trans *, struct xfs_buf *,
+18 −0
Original line number Diff line number Diff line
@@ -430,6 +430,24 @@ xfs_bmbt_lookup_ge(
	return xfs_btree_lookup(cur, XFS_LOOKUP_GE, stat);
}

/*
* Update the record referred to by cur to the value given
 * by [off, bno, len, state].
 * This either works (return 0) or gets an EFSCORRUPTED error.
 */
STATIC int
xfs_bmbt_update(
	struct xfs_btree_cur	*cur,
	xfs_fileoff_t		off,
	xfs_fsblock_t		bno,
	xfs_filblks_t		len,
	xfs_exntst_t		state)
{
	union xfs_btree_rec	rec;

	xfs_bmbt_disk_set_allf(&rec.bmbt, off, bno, len, state);
	return xfs_btree_update(cur, &rec);
}

/*
 * Called from xfs_bmap_add_attrfork to handle btree format files.
+0 −45
Original line number Diff line number Diff line
@@ -1963,51 +1963,6 @@ xfs_bmbt_to_bmdr(
	memcpy(tpp, fpp, sizeof(*fpp) * dmxr);
}

/*
 * Update the record to the passed values.
 */
int
xfs_bmbt_update(
	xfs_btree_cur_t		*cur,
	xfs_fileoff_t		off,
	xfs_fsblock_t		bno,
	xfs_filblks_t		len,
	xfs_exntst_t		state)
{
	xfs_bmbt_block_t	*block;
	xfs_buf_t		*bp;
	int			error;
	xfs_bmbt_key_t		key;
	int			ptr;
	xfs_bmbt_rec_t		*rp;

	XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
	XFS_BMBT_TRACE_ARGFFFI(cur, (xfs_dfiloff_t)off, (xfs_dfsbno_t)bno,
		(xfs_dfilblks_t)len, (int)state);
	block = xfs_bmbt_get_block(cur, 0, &bp);
#ifdef DEBUG
	if ((error = xfs_btree_check_lblock(cur, block, 0, bp))) {
		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
		return error;
	}
#endif
	ptr = cur->bc_ptrs[0];
	rp = XFS_BMAP_REC_IADDR(block, ptr, cur);
	xfs_bmbt_disk_set_allf(rp, off, bno, len, state);
	xfs_bmbt_log_recs(cur, bp, ptr, ptr);
	if (ptr > 1) {
		XFS_BMBT_TRACE_CURSOR(cur, EXIT);
		return 0;
	}
	key.br_startoff = cpu_to_be64(off);
	if ((error = xfs_btree_updkey(cur, (union xfs_btree_key *)&key, 1))) {
		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
		return error;
	}
	XFS_BMBT_TRACE_CURSOR(cur, EXIT);
	return 0;
}

/*
 * Check extent records, which have just been read, for
 * any bit in the extent flag field. ASSERT on debug
Loading