]> git.karo-electronics.de Git - linux-beck.git/commitdiff
xfs: split xfs_bmap_btalloc_nullfb
authorChristoph Hellwig <hch@lst.de>
Tue, 22 Apr 2014 21:11:41 +0000 (07:11 +1000)
committerDave Chinner <david@fromorbit.com>
Tue, 22 Apr 2014 21:11:41 +0000 (07:11 +1000)
Split xfs_bmap_btalloc_nullfb into one function for filestream allocations
and one for everything else that share a few helpers.  This dramatically
simplifies the control flow.

Signed-off-by: Christoph Hellwig <hch@lst.de>
fs/xfs/xfs_bmap.c

index 38e88a01b4470b074549e743f16a61978e52758b..b0758656c1c300d43caa57f9eeaadb9639e3e21c 100644 (file)
@@ -3517,6 +3517,67 @@ xfs_bmap_adjacent(
 #undef ISVALID
 }
 
+static int
+xfs_bmap_longest_free_extent(
+       struct xfs_trans        *tp,
+       xfs_agnumber_t          ag,
+       xfs_extlen_t            *blen,
+       int                     *notinit)
+{
+       struct xfs_mount        *mp = tp->t_mountp;
+       struct xfs_perag        *pag;
+       xfs_extlen_t            longest;
+       int                     error = 0;
+
+       pag = xfs_perag_get(mp, ag);
+       if (!pag->pagf_init) {
+               error = xfs_alloc_pagf_init(mp, tp, ag, XFS_ALLOC_FLAG_TRYLOCK);
+               if (error)
+                       goto out;
+
+               if (!pag->pagf_init) {
+                       *notinit = 1;
+                       goto out;
+               }
+       }
+
+       longest = xfs_alloc_longest_free_extent(mp, pag);
+       if (*blen < longest)
+               *blen = longest;
+
+out:
+       xfs_perag_put(pag);
+       return error;
+}
+
+static void
+xfs_bmap_select_minlen(
+       struct xfs_bmalloca     *ap,
+       struct xfs_alloc_arg    *args,
+       xfs_extlen_t            *blen,
+       int                     notinit)
+{
+       if (notinit || *blen < ap->minlen) {
+               /*
+                * Since we did a BUF_TRYLOCK above, it is possible that
+                * there is space for this request.
+                */
+               args->minlen = ap->minlen;
+       } else if (*blen < args->maxlen) {
+               /*
+                * If the best seen length is less than the request length,
+                * use the best as the minimum.
+                */
+               args->minlen = *blen;
+       } else {
+               /*
+                * Otherwise we've seen an extent as big as maxlen, use that
+                * as the minimum.
+                */
+               args->minlen = args->maxlen;
+       }
+}
+
 STATIC int
 xfs_bmap_btalloc_nullfb(
        struct xfs_bmalloca     *ap,
@@ -3524,109 +3585,74 @@ xfs_bmap_btalloc_nullfb(
        xfs_extlen_t            *blen)
 {
        struct xfs_mount        *mp = ap->ip->i_mount;
-       struct xfs_perag        *pag;
        xfs_agnumber_t          ag, startag;
        int                     notinit = 0;
        int                     error;
 
-       if (ap->userdata && xfs_inode_is_filestream(ap->ip))
-               args->type = XFS_ALLOCTYPE_NEAR_BNO;
-       else
-               args->type = XFS_ALLOCTYPE_START_BNO;
+       args->type = XFS_ALLOCTYPE_START_BNO;
        args->total = ap->total;
 
-       /*
-        * Search for an allocation group with a single extent large enough
-        * for the request.  If one isn't found, then adjust the minimum
-        * allocation size to the largest space found.
-        */
        startag = ag = XFS_FSB_TO_AGNO(mp, args->fsbno);
        if (startag == NULLAGNUMBER)
                startag = ag = 0;
 
-       pag = xfs_perag_get(mp, ag);
        while (*blen < args->maxlen) {
-               if (!pag->pagf_init) {
-                       error = xfs_alloc_pagf_init(mp, args->tp, ag,
-                                                   XFS_ALLOC_FLAG_TRYLOCK);
-                       if (error) {
-                               xfs_perag_put(pag);
-                               return error;
-                       }
-               }
-
-               /*
-                * See xfs_alloc_fix_freelist...
-                */
-               if (pag->pagf_init) {
-                       xfs_extlen_t    longest;
-                       longest = xfs_alloc_longest_free_extent(mp, pag);
-                       if (*blen < longest)
-                               *blen = longest;
-               } else
-                       notinit = 1;
-
-               if (xfs_inode_is_filestream(ap->ip) && ap->userdata) {
-                       if (*blen >= args->maxlen)
-                               break;
-
-                       /*
-                        * If startag is an invalid AG, we've
-                        * come here once before and
-                        * xfs_filestream_new_ag picked the
-                        * best currently available.
-                        *
-                        * Don't continue looping, since we
-                        * could loop forever.
-                        */
-                       if (startag == NULLAGNUMBER)
-                               break;
-
-                       error = xfs_filestream_new_ag(ap, &ag);
-                       xfs_perag_put(pag);
-                       if (error)
-                               return error;
+               error = xfs_bmap_longest_free_extent(args->tp, ag, blen,
+                                                    &notinit);
+               if (error)
+                       return error;
 
-                       /* loop again to set 'blen'*/
-                       startag = NULLAGNUMBER;
-                       pag = xfs_perag_get(mp, ag);
-                       continue;
-               }
                if (++ag == mp->m_sb.sb_agcount)
                        ag = 0;
                if (ag == startag)
                        break;
-               xfs_perag_put(pag);
-               pag = xfs_perag_get(mp, ag);
        }
-       xfs_perag_put(pag);
 
-       /*
-        * Since the above loop did a BUF_TRYLOCK, it is
-        * possible that there is space for this request.
-        */
-       if (notinit || *blen < ap->minlen)
-               args->minlen = ap->minlen;
-       /*
-        * If the best seen length is less than the request
-        * length, use the best as the minimum.
-        */
-       else if (*blen < args->maxlen)
-               args->minlen = *blen;
-       /*
-        * Otherwise we've seen an extent as big as maxlen,
-        * use that as the minimum.
-        */
-       else
-               args->minlen = args->maxlen;
+       xfs_bmap_select_minlen(ap, args, blen, notinit);
+       return 0;
+}
+
+STATIC int
+xfs_bmap_btalloc_filestreams(
+       struct xfs_bmalloca     *ap,
+       struct xfs_alloc_arg    *args,
+       xfs_extlen_t            *blen)
+{
+       struct xfs_mount        *mp = ap->ip->i_mount;
+       xfs_agnumber_t          ag;
+       int                     notinit = 0;
+       int                     error;
+
+       args->type = XFS_ALLOCTYPE_NEAR_BNO;
+       args->total = ap->total;
+
+       ag = XFS_FSB_TO_AGNO(mp, args->fsbno);
+       if (ag == NULLAGNUMBER)
+               ag = 0;
+
+       error = xfs_bmap_longest_free_extent(args->tp, ag, blen, &notinit);
+       if (error)
+               return error;
+
+       if (*blen < args->maxlen) {
+               error = xfs_filestream_new_ag(ap, &ag);
+               if (error)
+                       return error;
+
+               error = xfs_bmap_longest_free_extent(args->tp, ag, blen,
+                                                    &notinit);
+               if (error)
+                       return error;
+
+       }
+
+       xfs_bmap_select_minlen(ap, args, blen, notinit);
 
        /*
-        * set the failure fallback case to look in the selected
-        * AG as the stream may have moved.
+        * Set the failure fallback case to look in the selected AG as stream
+        * may have moved.
         */
-       if (xfs_inode_is_filestream(ap->ip))
-               ap->blkno = args->fsbno = XFS_AGB_TO_FSB(mp, ag, 0);
-
+       ap->blkno = args->fsbno = XFS_AGB_TO_FSB(mp, ag, 0);
        return 0;
 }
 
@@ -3706,7 +3732,15 @@ xfs_bmap_btalloc(
        args.firstblock = *ap->firstblock;
        blen = 0;
        if (nullfb) {
-               error = xfs_bmap_btalloc_nullfb(ap, &args, &blen);
+               /*
+                * Search for an allocation group with a single extent large
+                * enough for the request.  If one isn't found, then adjust
+                * the minimum allocation size to the largest space found.
+                */
+               if (ap->userdata && xfs_inode_is_filestream(ap->ip))
+                       error = xfs_bmap_btalloc_filestreams(ap, &args, &blen);
+               else
+                       error = xfs_bmap_btalloc_nullfb(ap, &args, &blen);
                if (error)
                        return error;
        } else if (ap->flist->xbf_low) {