diff options
author | Christoph Hellwig <hch@infradead.org> | 2011-05-20 09:45:32 -0400 |
---|---|---|
committer | Alex Elder <aelder@sgi.com> | 2011-05-24 12:17:13 -0400 |
commit | e84661aa84e2e003738563f65155d4f12dc474e7 (patch) | |
tree | 9f9b6d2fac2048c5fb8c2728bcf2930435890d4f /fs/xfs/xfs_alloc.c | |
parent | bf59170a66bc3eaf3ee513aa6ce9774aa2ab5188 (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.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) { |