aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_alloc.c
diff options
context:
space:
mode:
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) {