diff options
Diffstat (limited to 'fs/xfs/xfs_alloc.c')
-rw-r--r-- | fs/xfs/xfs_alloc.c | 28 |
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 | */ | ||
2982 | void | 3000 | void |
2983 | xfs_alloc_busy_clear( | 3001 | xfs_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) { |