xfs
[Top] [All Lists]

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

To: linux-xfs@xxxxxxxxxxxxxxx
Subject: [PATCH 6/6] xfs: use per-ag AGFL indexes everywhere
From: Dave Chinner <david@xxxxxxxxxxxxx>
Date: Fri, 2 Sep 2016 12:27:37 +1000
Cc: xfs@xxxxxxxxxxx
Delivered-to: xfs@xxxxxxxxxxx
In-reply-to: <1472783257-15941-1-git-send-email-david@xxxxxxxxxxxxx>
References: <1472783257-15941-1-git-send-email-david@xxxxxxxxxxxxx>
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

<Prev in Thread] Current Thread [Next in Thread>