[PATCH 6/6] xfs: use per-ag AGFL indexes everywhere

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Dave Chinner <dchinner@xxxxxxxxxx>

Now we have the AGFL indexes in the struct xfs_perag, use them
everywhere rather than having to decode them directly from the AGF
buffer. This essentially makes the values in the perag the primary
in-memory copy of the free list state, so we operate on that first
then copy them to the on-disk structure just before logging them.

This removes a lot of endian conversions that are done to manipulate
the on-disk structures, making the frequently called
xfs_alloc_get/put_freelist() substantially more compact and faster.

text	   data	    bss	    dec	    hex	filename
 835459	 157358	   1008	 993825	  f2a21	fs/xfs/xfs.o.old
 835299	 157358	   1008	 993665	  f2981	fs/xfs/xfs.o.new

Signed-off-by: Dave Chinner <dchinner@xxxxxxxxxx>
---
 fs/xfs/libxfs/xfs_alloc.c | 135 ++++++++++++++++++++++------------------------
 1 file changed, 64 insertions(+), 71 deletions(-)

diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c
index 8deb736..554f033 100644
--- a/fs/xfs/libxfs/xfs_alloc.c
+++ b/fs/xfs/libxfs/xfs_alloc.c
@@ -2220,66 +2220,62 @@ out_no_agbp:
  * Get a block from the freelist.
  * Returns with the buffer for the block gotten.
  */
-int				/* error */
+int
 xfs_alloc_get_freelist(
-	xfs_trans_t	*tp,	/* transaction pointer */
-	xfs_buf_t	*agbp,	/* buffer containing the agf structure */
-	xfs_agblock_t	*bnop,	/* block address retrieved from freelist */
+	struct xfs_trans *tp,
+	struct xfs_buf	*agbp,
+	xfs_agblock_t	*bnop,
 	int		btreeblk) /* destination is a AGF btree */
 {
-	xfs_agf_t	*agf;	/* a.g. freespace structure */
-	xfs_buf_t	*agflbp;/* buffer for a.g. freelist structure */
-	xfs_agblock_t	bno;	/* block number returned */
+	struct xfs_mount *mp = tp->t_mountp;
+	struct xfs_agf	*agf = XFS_BUF_TO_AGF(agbp);
+	struct xfs_buf	*agflbp;
+	struct xfs_perag *pag;
+	xfs_agnumber_t	agno = be32_to_cpu(agf->agf_seqno);
+	xfs_agblock_t	bno = NULLAGBLOCK;
 	__be32		*agfl_bno;
 	int		error;
 	int		logflags;
-	xfs_mount_t	*mp = tp->t_mountp;
-	xfs_perag_t	*pag;	/* per allocation group data */
 
-	/*
-	 * Freelist is empty, give up.
-	 */
-	agf = XFS_BUF_TO_AGF(agbp);
-	if (!agf->agf_flcount) {
-		*bnop = NULLAGBLOCK;
-		return 0;
-	}
+	/* Freelist is empty, give up. */
+	pag = xfs_perag_get(mp, agno);
+	if (!pag->pagf_flcount)
+		goto out_put_perag;
+
 	/*
 	 * Read the array of free blocks.
 	 */
-	error = xfs_alloc_read_agfl(mp, tp, be32_to_cpu(agf->agf_seqno),
-				    &agflbp);
+	error = xfs_alloc_read_agfl(mp, tp, agno, &agflbp);
 	if (error)
 		return error;
 
+	agfl_bno = XFS_BUF_TO_AGFL_BNO(mp, agflbp);
+	logflags = XFS_AGF_FLFIRST | XFS_AGF_FLCOUNT;
 
 	/*
 	 * Get the block number and update the data structures.
 	 */
-	agfl_bno = XFS_BUF_TO_AGFL_BNO(mp, agflbp);
-	bno = be32_to_cpu(agfl_bno[be32_to_cpu(agf->agf_flfirst)]);
-	be32_add_cpu(&agf->agf_flfirst, 1);
-	xfs_trans_brelse(tp, agflbp);
-	if (be32_to_cpu(agf->agf_flfirst) == xfs_agfl_size(mp))
-		agf->agf_flfirst = 0;
-
-	pag = xfs_perag_get(mp, be32_to_cpu(agf->agf_seqno));
-	be32_add_cpu(&agf->agf_flcount, -1);
-	xfs_trans_agflist_delta(tp, -1);
+	bno = be32_to_cpu(agfl_bno[pag->pagf_flfirst]);
+	if (++pag->pagf_flfirst == xfs_agfl_size(mp))
+		pag->pagf_flfirst = 0;
 	pag->pagf_flcount--;
-	pag->pagf_flfirst = be32_to_cpu(agf->agf_flfirst);
-	xfs_perag_put(pag);
+	xfs_trans_agflist_delta(tp, -1);
 
-	logflags = XFS_AGF_FLFIRST | XFS_AGF_FLCOUNT;
 	if (btreeblk) {
-		be32_add_cpu(&agf->agf_btreeblks, 1);
 		pag->pagf_btreeblks++;
+		agf->agf_btreeblks = cpu_to_be32(pag->pagf_btreeblks);
 		logflags |= XFS_AGF_BTREEBLKS;
 	}
 
+	agf->agf_flfirst = cpu_to_be32(pag->pagf_flfirst);
+	agf->agf_flcount = cpu_to_be32(pag->pagf_flcount);
+
+	xfs_trans_brelse(tp, agflbp);
 	xfs_alloc_log_agf(tp, agbp, logflags);
-	*bnop = bno;
 
+out_put_perag:
+	xfs_perag_put(pag);
+	*bnop = bno;
 	return 0;
 }
 
@@ -2345,53 +2341,51 @@ xfs_alloc_pagf_init(
 /*
  * Put the block on the freelist for the allocation group.
  */
-int					/* error */
+int
 xfs_alloc_put_freelist(
-	xfs_trans_t		*tp,	/* transaction pointer */
-	xfs_buf_t		*agbp,	/* buffer for a.g. freelist header */
-	xfs_buf_t		*agflbp,/* buffer for a.g. free block array */
-	xfs_agblock_t		bno,	/* block being freed */
+	struct xfs_trans	*tp,
+	struct xfs_buf		*agbp,
+	struct xfs_buf		*agflbp,
+	xfs_agblock_t		bno,
 	int			btreeblk) /* block came from a AGF btree */
 {
-	xfs_agf_t		*agf;	/* a.g. freespace structure */
-	__be32			*blockp;/* pointer to array entry */
+	struct xfs_mount	*mp = tp->t_mountp;
+	struct xfs_agf		*agf = XFS_BUF_TO_AGF(agbp);
+	struct xfs_perag	*pag;
+	xfs_agnumber_t		agno = be32_to_cpu(agf->agf_seqno);
+	__be32			*agfl_bno;
+	__be32			*blockp;
 	int			error;
 	int			logflags;
-	xfs_mount_t		*mp;	/* mount structure */
-	xfs_perag_t		*pag;	/* per allocation group data */
-	__be32			*agfl_bno;
 	int			startoff;
 
-	agf = XFS_BUF_TO_AGF(agbp);
-	mp = tp->t_mountp;
+	if (!agflbp) {
+		error = xfs_alloc_read_agfl(mp, tp, agno, &agflbp);
+		if (error)
+			return error;
+	}
 
-	if (!agflbp && (error = xfs_alloc_read_agfl(mp, tp,
-			be32_to_cpu(agf->agf_seqno), &agflbp)))
-		return error;
-	be32_add_cpu(&agf->agf_fllast, 1);
-	if (be32_to_cpu(agf->agf_fllast) == xfs_agfl_size(mp))
-		agf->agf_fllast = 0;
+	logflags = XFS_AGF_FLLAST | XFS_AGF_FLCOUNT;
 
-	pag = xfs_perag_get(mp, be32_to_cpu(agf->agf_seqno));
-	be32_add_cpu(&agf->agf_flcount, 1);
-	xfs_trans_agflist_delta(tp, 1);
+	pag = xfs_perag_get(mp, agno);
 	pag->pagf_flcount++;
-	pag->pagf_fllast = be32_to_cpu(agf->agf_fllast);
+	ASSERT(pag->pagf_flcount <= xfs_agfl_size(mp));
 
-	logflags = XFS_AGF_FLLAST | XFS_AGF_FLCOUNT;
+	if (++pag->pagf_fllast == xfs_agfl_size(mp))
+		pag->pagf_fllast = 0;
+	xfs_trans_agflist_delta(tp, 1);
 	if (btreeblk) {
-		be32_add_cpu(&agf->agf_btreeblks, -1);
 		pag->pagf_btreeblks--;
+		agf->agf_btreeblks = cpu_to_be32(pag->pagf_btreeblks);
 		logflags |= XFS_AGF_BTREEBLKS;
 	}
-	xfs_perag_put(pag);
 
-	xfs_alloc_log_agf(tp, agbp, logflags);
+	agf->agf_fllast = cpu_to_be32(pag->pagf_fllast);
+	agf->agf_flcount = cpu_to_be32(pag->pagf_flcount);
 
-	ASSERT(be32_to_cpu(agf->agf_flcount) <= xfs_agfl_size(mp));
 
 	agfl_bno = XFS_BUF_TO_AGFL_BNO(mp, agflbp);
-	blockp = &agfl_bno[be32_to_cpu(agf->agf_fllast)];
+	blockp = &agfl_bno[pag->pagf_fllast];
 	*blockp = cpu_to_be32(bno);
 	startoff = (char *)blockp - (char *)agflbp->b_addr;
 
@@ -2400,6 +2394,7 @@ xfs_alloc_put_freelist(
 	xfs_trans_buf_set_type(tp, agflbp, XFS_BLFT_AGFL_BUF);
 	xfs_trans_log_buf(tp, agflbp, startoff,
 			  startoff + sizeof(xfs_agblock_t) - 1);
+	xfs_perag_put(pag);
 	return 0;
 }
 
@@ -2612,18 +2607,14 @@ xfs_agf_fixup_freelist_count(
 			   pag->pag_agno);
 		if (pag->pagf_flcount) {
 			pag->pagf_flcount--;
-			be32_add_cpu(&agf->agf_flcount, -1);
-			be32_add_cpu(&agf->agf_fllast, -1);
 			pag->pagf_fllast--;
 		} else {
 			/* empty free list, move the both pointers back one */
 			ASSERT(pag->pagf_flfirst == pag->pagf_fllast);
-			be32_add_cpu(&agf->agf_fllast, -1);
-			be32_add_cpu(&agf->agf_flfirst, -1);
 			pag->pagf_flfirst--;
 			pag->pagf_fllast--;
 		}
-		return;
+		goto out_update_agf;
 	}
 
 	/* if first is invalid, wrap it, reset count and return */
@@ -2633,10 +2624,8 @@ xfs_agf_fixup_freelist_count(
 		ASSERT(pag->pagf_flfirst != pag->pagf_fllast);
 		ASSERT(pag->pagf_flcount);
 		pag->pagf_flcount = pag->pagf_fllast + 1;
-		agf->agf_flcount = cpu_to_be32(pag->pagf_flcount);
-		agf->agf_flfirst = 0;
 		pag->pagf_flfirst = 0;
-		return;
+		goto out_update_agf;
 	}
 
 	/*
@@ -2662,7 +2651,11 @@ xfs_agf_fixup_freelist_count(
 	xfs_notice(mp, "AGF %d: wrapped count fixup being performed",
 		   pag->pag_agno);
 	pag->pagf_flcount--;
-	be32_add_cpu(&agf->agf_flcount, -1);
+
+out_update_agf:
+	agf->agf_flfirst = cpu_to_be32(pag->pagf_flfirst);
+	agf->agf_fllast = cpu_to_be32(pag->pagf_fllast);
+	agf->agf_flcount = cpu_to_be32(pag->pagf_flcount);
 }
 
 /*
-- 
2.8.0.rc3

_______________________________________________
xfs mailing list
xfs@xxxxxxxxxxx
http://oss.sgi.com/mailman/listinfo/xfs



[Index of Archives]     [Linux XFS Devel]     [Linux Filesystem Development]     [Filesystem Testing]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux