xfs: do not discard alloc btree blocks
authorChristoph Hellwig <hch@infradead.org>
Wed, 4 May 2011 18:55:15 +0000 (18:55 +0000)
committerAlex Elder <aelder@sgi.com>
Tue, 24 May 2011 16:17:22 +0000 (11:17 -0500)
Blocks for the allocation btree are allocated from and released to
the AGFL, and thus frequently reused.  Even worse we do not have an
easy way to avoid using an AGFL block when it is discarded due to
the simple FILO list of free blocks, and thus can frequently stall
on blocks that are currently undergoing a discard.

Add a flag to the busy extent tracking structure to skip the discard
for allocation btree blocks.  In normal operation these blocks are
reused frequently enough that there is no need to discard them
anyway, but if they spill over to the allocation btree as part of a
balance we "leak" blocks that we would otherwise discard.  We could
fix this by adding another flag and keeping these block in the
rbtree even after they aren't busy any more so that we could discard
them when they migrate out of the AGFL.  Given that this would cause
significant overhead I don't think it's worthwile for now.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Alex Elder <aelder@sgi.com>
fs/xfs/xfs_ag.h
fs/xfs/xfs_alloc.c
fs/xfs/xfs_alloc.h
fs/xfs/xfs_alloc_btree.c

index 8d52ba4c87e54314f5106bd19bc92a3626a3f2da..6530769a999bdb045ba4ec5d1588440a04993e1c 100644 (file)
@@ -189,6 +189,7 @@ struct xfs_busy_extent {
        xfs_extlen_t    length;
        unsigned int    flags;
 #define XFS_ALLOC_BUSY_DISCARDED       0x01    /* undergoing a discard op. */
+#define XFS_ALLOC_BUSY_SKIP_DISCARD    0x02    /* do not discard */
 };
 
 /*
index 721db22c6ec9e29bd4448d01eb6c0caf2486bb3e..95862bbff56bf0cf8c82d4e88178dc43408866d7 100644 (file)
@@ -2469,7 +2469,7 @@ xfs_free_extent(
 
        error = xfs_free_ag_extent(tp, args.agbp, args.agno, args.agbno, len, 0);
        if (!error)
-               xfs_alloc_busy_insert(tp, args.agno, args.agbno, len);
+               xfs_alloc_busy_insert(tp, args.agno, args.agbno, len, 0);
 error0:
        xfs_perag_put(args.pag);
        return error;
@@ -2480,7 +2480,8 @@ xfs_alloc_busy_insert(
        struct xfs_trans        *tp,
        xfs_agnumber_t          agno,
        xfs_agblock_t           bno,
-       xfs_extlen_t            len)
+       xfs_extlen_t            len,
+       unsigned int            flags)
 {
        struct xfs_busy_extent  *new;
        struct xfs_busy_extent  *busyp;
@@ -2504,6 +2505,7 @@ xfs_alloc_busy_insert(
        new->bno = bno;
        new->length = len;
        INIT_LIST_HEAD(&new->list);
+       new->flags = flags;
 
        /* trace before insert to be able to see failed inserts */
        trace_xfs_alloc_busy(tp->t_mountp, agno, bno, len);
@@ -3018,7 +3020,8 @@ xfs_alloc_busy_clear(
                        agno = busyp->agno;
                }
 
-               if (do_discard && busyp->length)
+               if (do_discard && busyp->length &&
+                   !(busyp->flags & XFS_ALLOC_BUSY_SKIP_DISCARD))
                        busyp->flags = XFS_ALLOC_BUSY_DISCARDED;
                else
                        xfs_alloc_busy_clear_one(mp, pag, busyp);
index 06aa8217452b511811b631fa50be303bba6dc56b..2f52b924be79f424b0a3115849af602f719a6b79 100644 (file)
@@ -137,7 +137,7 @@ xfs_alloc_longest_free_extent(struct xfs_mount *mp,
 #ifdef __KERNEL__
 void
 xfs_alloc_busy_insert(struct xfs_trans *tp, xfs_agnumber_t agno,
-       xfs_agblock_t bno, xfs_extlen_t len);
+       xfs_agblock_t bno, xfs_extlen_t len, unsigned int flags);
 
 void
 xfs_alloc_busy_clear(struct xfs_mount *mp, struct list_head *list,
index 8b469d53599fb4b35cd0851a0baef7e916787969..2b3518826a692640c46e3e4fb5f5192e418e868b 100644 (file)
@@ -120,7 +120,8 @@ xfs_allocbt_free_block(
        if (error)
                return error;
 
-       xfs_alloc_busy_insert(cur->bc_tp, be32_to_cpu(agf->agf_seqno), bno, 1);
+       xfs_alloc_busy_insert(cur->bc_tp, be32_to_cpu(agf->agf_seqno), bno, 1,
+                             XFS_ALLOC_BUSY_SKIP_DISCARD);
        xfs_trans_agbtree_delta(cur->bc_tp, -1);
        return 0;
 }