xfs
[Top] [All Lists]

[PATCH 5/7] xfs: refactor xfs_ialloc_ag_select

To: xfs@xxxxxxxxxxx
Subject: [PATCH 5/7] xfs: refactor xfs_ialloc_ag_select
From: Christoph Hellwig <hch@xxxxxxxxxxxxx>
Date: Tue, 05 Jun 2012 10:46:52 -0400
References: <20120605144647.051012936@xxxxxxxxxxxxxxxxxxxxxx>
User-agent: quilt/0.48-1
Loop over the in-core perag structures and prefer using pagi_freecount over
going out to the AGI buffer where possible.

Signed-off-by: Christoph Hellwig <hch@xxxxxx>

---
 fs/xfs/xfs_ialloc.c |   96 ++++++++++++++++++++++++----------------------------
 1 file changed, 46 insertions(+), 50 deletions(-)

Index: xfs/fs/xfs/xfs_ialloc.c
===================================================================
--- xfs.orig/fs/xfs/xfs_ialloc.c        2012-06-04 12:49:31.000000000 -0400
+++ xfs/fs/xfs/xfs_ialloc.c     2012-06-04 12:54:53.000258389 -0400
@@ -442,14 +442,13 @@ xfs_ialloc_next_ag(
  * Select an allocation group to look for a free inode in, based on the parent
  * inode and then mode.  Return the allocation group buffer.
  */
-STATIC xfs_buf_t *                     /* allocation group buffer */
+STATIC xfs_agnumber_t
 xfs_ialloc_ag_select(
        xfs_trans_t     *tp,            /* transaction pointer */
        xfs_ino_t       parent,         /* parent directory inode number */
        umode_t         mode,           /* bits set to indicate file type */
        int             okalloc)        /* ok to allocate more space */
 {
-       xfs_buf_t       *agbp;          /* allocation group header buffer */
        xfs_agnumber_t  agcount;        /* number of ag's in the filesystem */
        xfs_agnumber_t  agno;           /* current ag number */
        int             flags;          /* alloc buffer locking flags */
@@ -459,6 +458,7 @@ xfs_ialloc_ag_select(
        int             needspace;      /* file mode implies space allocated */
        xfs_perag_t     *pag;           /* per allocation group data */
        xfs_agnumber_t  pagno;          /* parent (starting) ag number */
+       int             error;
 
        /*
         * Files of these types need at least one block if length > 0
@@ -474,7 +474,9 @@ xfs_ialloc_ag_select(
                if (pagno >= agcount)
                        pagno = 0;
        }
+
        ASSERT(pagno < agcount);
+
        /*
         * Loop through allocation groups, looking for one with a little
         * free space in it.  Note we don't look for free inodes, exactly.
@@ -486,51 +488,45 @@ xfs_ialloc_ag_select(
        flags = XFS_ALLOC_FLAG_TRYLOCK;
        for (;;) {
                pag = xfs_perag_get(mp, agno);
+               if (!pag->pagi_inodeok) {
+                       xfs_ialloc_next_ag(mp);
+                       goto nextag;
+               }
+
                if (!pag->pagi_init) {
-                       if (xfs_ialloc_read_agi(mp, tp, agno, &agbp)) {
-                               agbp = NULL;
+                       error = xfs_ialloc_pagi_init(mp, tp, agno);
+                       if (error)
                                goto nextag;
-                       }
-               } else
-                       agbp = NULL;
+               }
 
-               if (!pag->pagi_inodeok) {
-                       xfs_ialloc_next_ag(mp);
-                       goto unlock_nextag;
+               if (pag->pagi_freecount) {
+                       xfs_perag_put(pag);
+                       return agno;
                }
 
-               /*
-                * Is there enough free space for the file plus a block
-                * of inodes (if we need to allocate some)?
-                */
-               ineed = pag->pagi_freecount ? 0 : XFS_IALLOC_BLOCKS(mp);
-               if (ineed && !pag->pagf_init) {
-                       if (agbp == NULL &&
-                           xfs_ialloc_read_agi(mp, tp, agno, &agbp)) {
-                               agbp = NULL;
+               if (!okalloc)
+                       goto nextag;
+
+               if (!pag->pagf_init) {
+                       error = xfs_alloc_pagf_init(mp, tp, agno, flags);
+                       if (error)
                                goto nextag;
-                       }
-                       (void)xfs_alloc_pagf_init(mp, tp, agno, flags);
                }
-               if (!ineed || pag->pagf_init) {
-                       if (ineed && !(longest = pag->pagf_longest))
-                               longest = pag->pagf_flcount > 0;
-                       if (!ineed ||
-                           (pag->pagf_freeblks >= needspace + ineed &&
-                            longest >= ineed &&
-                            okalloc)) {
-                               if (agbp == NULL &&
-                                   xfs_ialloc_read_agi(mp, tp, agno, &agbp)) {
-                                       agbp = NULL;
-                                       goto nextag;
-                               }
-                               xfs_perag_put(pag);
-                               return agbp;
-                       }
+
+               /*
+                * Is there enough free space for the file plus a block of
+                * inodes? (if we need to allocate some)?
+                */
+               ineed = XFS_IALLOC_BLOCKS(mp);
+               longest = pag->pagf_longest;
+               if (!longest)
+                       longest = pag->pagf_flcount > 0;
+
+               if (pag->pagf_freeblks >= needspace + ineed &&
+                   longest >= ineed) {
+                       xfs_perag_put(pag);
+                       return agno;
                }
-unlock_nextag:
-               if (agbp)
-                       xfs_trans_brelse(tp, agbp);
 nextag:
                xfs_perag_put(pag);
                /*
@@ -538,13 +534,13 @@ nextag:
                 * down.
                 */
                if (XFS_FORCED_SHUTDOWN(mp))
-                       return NULL;
+                       return NULLAGNUMBER;
                agno++;
                if (agno >= agcount)
                        agno = 0;
                if (agno == pagno) {
                        if (flags == 0)
-                               return NULL;
+                               return NULLAGNUMBER;
                        flags = 0;
                }
        }
@@ -901,13 +897,13 @@ xfs_dialloc(
        xfs_buf_t       **IO_agbp,      /* in/out ag header's buffer */
        xfs_ino_t       *inop)          /* inode number allocated */
 {
+       xfs_mount_t     *mp = tp->t_mountp;
        xfs_buf_t       *agbp;          /* allocation group header's buffer */
        xfs_agnumber_t  agno;           /* allocation group number */
        xfs_agi_t       *agi;           /* allocation group header structure */
        int             error;          /* error return value */
        int             ialloced;       /* inode allocation status */
        int             noroom = 0;     /* no space for inode blk allocation */
-       xfs_mount_t     *mp;            /* file system mount structure */
        xfs_agnumber_t  tagno;          /* testing allocation group number */
        struct xfs_perag *pag;
 
@@ -925,20 +921,17 @@ xfs_dialloc(
         * We do not have an agbp, so select an initial allocation
         * group for inode allocation.
         */
-       agbp = xfs_ialloc_ag_select(tp, parent, mode, okalloc);
-
-       /*
-        * Couldn't find an allocation group satisfying the
-        * criteria, give up.
-        */
-       if (!agbp) {
+       agno = xfs_ialloc_ag_select(tp, parent, mode, okalloc);
+       if (agno == NULLAGNUMBER) {
                *inop = NULLFSINO;
                return 0;
        }
+
+       error = xfs_ialloc_read_agi(mp, tp, agno, &agbp);
+       if (error)
+               return XFS_ERROR(error);
        agi = XFS_BUF_TO_AGI(agbp);
 
-       mp = tp->t_mountp;
-       agno = be32_to_cpu(agi->agi_seqno);
        tagno = agno;
 
        /*

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