diff options
Diffstat (limited to 'fs/xfs/xfs_rtalloc.c')
-rw-r--r-- | fs/xfs/xfs_rtalloc.c | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c index 4165899cdc96..ca78b274cf57 100644 --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c @@ -2290,3 +2290,52 @@ err: xfs_trans_cancel(tp); return ret; } + +/* + * Find the next free realtime extent starting at @rtx and going no higher than + * @end_rtx. Set @rtx and @len_rtx to whatever free extents we find, or to + * @end_rtx if we find no space. + */ +int +xfs_rtalloc_find_freesp( + struct xfs_trans *tp, + xfs_rtxnum_t *rtx, + xfs_rtxnum_t end_rtx, + xfs_rtxlen_t *len_rtx) +{ + struct xfs_mount *mp = tp->t_mountp; + unsigned int max_rt_extlen; + int error; + + trace_xfs_rtalloc_find_freesp(mp, *rtx, end_rtx - *rtx); + + max_rt_extlen = xfs_rtb_to_rtxt(mp, XFS_MAX_BMBT_EXTLEN); + + while (*rtx < end_rtx) { + xfs_rtblock_t range_end_rtx; + int is_free = 0; + + /* Is the first block in the range free? */ + error = xfs_rtcheck_range(mp, tp, *rtx, 1, 1, &range_end_rtx, + &is_free); + if (error) + return error; + + /* Free or not, how many more rtx have the same status? */ + error = xfs_rtfind_forw(mp, tp, *rtx, end_rtx, + &range_end_rtx); + if (error) + return error; + + if (is_free) { + trace_xfs_rtalloc_find_freesp_done(mp, *rtx, *len_rtx); + *len_rtx = min_t(xfs_rtblock_t, max_rt_extlen, + range_end_rtx - *rtx + 1); + return 0; + } + + *rtx = range_end_rtx + 1; + } + + return 0; +} |