aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_alloc.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2011-05-20 09:45:32 -0400
committerAlex Elder <aelder@sgi.com>2011-05-24 12:17:13 -0400
commite84661aa84e2e003738563f65155d4f12dc474e7 (patch)
tree9f9b6d2fac2048c5fb8c2728bcf2930435890d4f /fs/xfs/xfs_alloc.c
parentbf59170a66bc3eaf3ee513aa6ce9774aa2ab5188 (diff)
xfs: add online discard support
Now that we have reliably tracking of deleted extents in a transaction we can easily implement "online" discard support which calls blkdev_issue_discard once a transaction commits. The actual discard is a two stage operation as we first have to mark the busy extent as not available for reuse before we can start the actual discard. Note that we don't bother supporting discard for the non-delaylog mode. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Alex Elder <aelder@sgi.com>
Diffstat (limited to 'fs/xfs/xfs_alloc.c')
-rw-r--r--fs/xfs/xfs_alloc.c28
1 files changed, 25 insertions, 3 deletions
diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c
index acdced86413c..721db22c6ec9 100644
--- a/fs/xfs/xfs_alloc.c
+++ b/fs/xfs/xfs_alloc.c
@@ -2609,6 +2609,18 @@ xfs_alloc_busy_update_extent(
2609 xfs_agblock_t bend = bbno + busyp->length; 2609 xfs_agblock_t bend = bbno + busyp->length;
2610 2610
2611 /* 2611 /*
2612 * This extent is currently being discarded. Give the thread
2613 * performing the discard a chance to mark the extent unbusy
2614 * and retry.
2615 */
2616 if (busyp->flags & XFS_ALLOC_BUSY_DISCARDED) {
2617 spin_unlock(&pag->pagb_lock);
2618 delay(1);
2619 spin_lock(&pag->pagb_lock);
2620 return false;
2621 }
2622
2623 /*
2612 * If there is a busy extent overlapping a user allocation, we have 2624 * If there is a busy extent overlapping a user allocation, we have
2613 * no choice but to force the log and retry the search. 2625 * no choice but to force the log and retry the search.
2614 * 2626 *
@@ -2813,7 +2825,8 @@ restart:
2813 * If this is a metadata allocation, try to reuse the busy 2825 * If this is a metadata allocation, try to reuse the busy
2814 * extent instead of trimming the allocation. 2826 * extent instead of trimming the allocation.
2815 */ 2827 */
2816 if (!args->userdata) { 2828 if (!args->userdata &&
2829 !(busyp->flags & XFS_ALLOC_BUSY_DISCARDED)) {
2817 if (!xfs_alloc_busy_update_extent(args->mp, args->pag, 2830 if (!xfs_alloc_busy_update_extent(args->mp, args->pag,
2818 busyp, fbno, flen, 2831 busyp, fbno, flen,
2819 false)) 2832 false))
@@ -2979,10 +2992,16 @@ xfs_alloc_busy_clear_one(
2979 kmem_free(busyp); 2992 kmem_free(busyp);
2980} 2993}
2981 2994
2995/*
2996 * Remove all extents on the passed in list from the busy extents tree.
2997 * If do_discard is set skip extents that need to be discarded, and mark
2998 * these as undergoing a discard operation instead.
2999 */
2982void 3000void
2983xfs_alloc_busy_clear( 3001xfs_alloc_busy_clear(
2984 struct xfs_mount *mp, 3002 struct xfs_mount *mp,
2985 struct list_head *list) 3003 struct list_head *list,
3004 bool do_discard)
2986{ 3005{
2987 struct xfs_busy_extent *busyp, *n; 3006 struct xfs_busy_extent *busyp, *n;
2988 struct xfs_perag *pag = NULL; 3007 struct xfs_perag *pag = NULL;
@@ -2999,7 +3018,10 @@ xfs_alloc_busy_clear(
2999 agno = busyp->agno; 3018 agno = busyp->agno;
3000 } 3019 }
3001 3020
3002 xfs_alloc_busy_clear_one(mp, pag, busyp); 3021 if (do_discard && busyp->length)
3022 busyp->flags = XFS_ALLOC_BUSY_DISCARDED;
3023 else
3024 xfs_alloc_busy_clear_one(mp, pag, busyp);
3003 } 3025 }
3004 3026
3005 if (pag) { 3027 if (pag) {