xfs: separate freelist fixing into a separate helper
authorDave Chinner <dchinner@redhat.com>
Tue, 21 Jun 2016 01:53:28 +0000 (11:53 +1000)
committerDave Chinner <david@fromorbit.com>
Tue, 21 Jun 2016 01:53:28 +0000 (11:53 +1000)
Break up xfs_free_extent() into a helper that fixes the freelist.
This helper will be used subsequently to ensure the freelist during
deferred rmap processing.

[darrick: refactor to put this at the head of the patchset]

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Dave Chinner <david@fromorbit.com>
fs/xfs/libxfs/xfs_alloc.c
fs/xfs/libxfs/xfs_alloc.h

index a708e38b494c702edb9105706555615dbb8cf8ea..638657a91335e4c0dc19c71244400ef680cb06e6 100644 (file)
@@ -2658,55 +2658,79 @@ error0:
        return error;
 }
 
-/*
- * Free an extent.
- * Just break up the extent address and hand off to xfs_free_ag_extent
- * after fixing up the freelist.
- */
-int                            /* error */
-xfs_free_extent(
-       xfs_trans_t     *tp,    /* transaction pointer */
-       xfs_fsblock_t   bno,    /* starting block number of extent */
-       xfs_extlen_t    len)    /* length of extent */
+/* Ensure that the freelist is at full capacity. */
+int
+xfs_free_extent_fix_freelist(
+       struct xfs_trans        *tp,
+       xfs_agnumber_t          agno,
+       struct xfs_buf          **agbp)
 {
-       xfs_alloc_arg_t args;
-       int             error;
+       struct xfs_alloc_arg    args;
+       int                     error;
 
-       ASSERT(len != 0);
-       memset(&args, 0, sizeof(xfs_alloc_arg_t));
+       memset(&args, 0, sizeof(struct xfs_alloc_arg));
        args.tp = tp;
        args.mp = tp->t_mountp;
+       args.agno = agno;
 
        /*
         * validate that the block number is legal - the enables us to detect
         * and handle a silent filesystem corruption rather than crashing.
         */
-       args.agno = XFS_FSB_TO_AGNO(args.mp, bno);
        if (args.agno >= args.mp->m_sb.sb_agcount)
                return -EFSCORRUPTED;
 
-       args.agbno = XFS_FSB_TO_AGBNO(args.mp, bno);
-       if (args.agbno >= args.mp->m_sb.sb_agblocks)
-               return -EFSCORRUPTED;
-
        args.pag = xfs_perag_get(args.mp, args.agno);
        ASSERT(args.pag);
 
        error = xfs_alloc_fix_freelist(&args, XFS_ALLOC_FLAG_FREEING);
        if (error)
-               goto error0;
+               goto out;
+
+       *agbp = args.agbp;
+out:
+       xfs_perag_put(args.pag);
+       return error;
+}
+
+/*
+ * Free an extent.
+ * Just break up the extent address and hand off to xfs_free_ag_extent
+ * after fixing up the freelist.
+ */
+int                            /* error */
+xfs_free_extent(
+       struct xfs_trans        *tp,    /* transaction pointer */
+       xfs_fsblock_t           bno,    /* starting block number of extent */
+       xfs_extlen_t            len)    /* length of extent */
+{
+       struct xfs_mount        *mp = tp->t_mountp;
+       struct xfs_buf          *agbp;
+       xfs_agnumber_t          agno = XFS_FSB_TO_AGNO(mp, bno);
+       xfs_agblock_t           agbno = XFS_FSB_TO_AGBNO(mp, bno);
+       int                     error;
+
+       ASSERT(len != 0);
+
+       error = xfs_free_extent_fix_freelist(tp, agno, &agbp);
+       if (error)
+               return error;
+
+       XFS_WANT_CORRUPTED_GOTO(mp, agbno < mp->m_sb.sb_agblocks, err);
 
        /* validate the extent size is legal now we have the agf locked */
-       if (args.agbno + len >
-                       be32_to_cpu(XFS_BUF_TO_AGF(args.agbp)->agf_length)) {
-               error = -EFSCORRUPTED;
-               goto error0;
-       }
+       XFS_WANT_CORRUPTED_GOTO(mp,
+               agbno + len <= be32_to_cpu(XFS_BUF_TO_AGF(agbp)->agf_length),
+                               err);
 
-       error = xfs_free_ag_extent(tp, args.agbp, args.agno, args.agbno, len, 0);
-       if (!error)
-               xfs_extent_busy_insert(tp, args.agno, args.agbno, len, 0);
-error0:
-       xfs_perag_put(args.pag);
+       error = xfs_free_ag_extent(tp, agbp, agno, agbno, len, 0);
+       if (error)
+               goto err;
+
+       xfs_extent_busy_insert(tp, agno, agbno, len, 0);
+       return 0;
+
+err:
+       xfs_trans_brelse(tp, agbp);
        return error;
 }
index 135eb3d24db7166bcafb659ab192d25f5ad6a104..f5b35dc594de3d475235152728b5a75d237dbbd3 100644 (file)
@@ -236,5 +236,7 @@ xfs_alloc_get_rec(
 int xfs_read_agf(struct xfs_mount *mp, struct xfs_trans *tp,
                        xfs_agnumber_t agno, int flags, struct xfs_buf **bpp);
 int xfs_alloc_fix_freelist(struct xfs_alloc_arg *args, int flags);
+int xfs_free_extent_fix_freelist(struct xfs_trans *tp, xfs_agnumber_t agno,
+               struct xfs_buf **agbp);
 
 #endif /* __XFS_ALLOC_H__ */