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 7f5f90821ead..e7cf800bb772 100644 --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c @@ -1840,3 +1840,52 @@ xfs_rtunlock( if ((lock_flags & XFS_RTLOCK_REFCOUNT) && mp->m_rrefcountip) xfs_iunlock(mp->m_rrefcountip, XFS_ILOCK_EXCL); } + +/* + * 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_rtblock_t *rtx, + xfs_rtblock_t end_rtx, + xfs_extlen_t *len_rtx) +{ + struct xfs_mount *mp = tp->t_mountp; + unsigned int MAXRTEXTLEN; + int error; + + trace_xfs_rtalloc_find_freesp(mp, *rtx, end_rtx - *rtx); + + MAXRTEXTLEN = div_u64(MAXEXTLEN, mp->m_sb.sb_rextsize); + + 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, MAXRTEXTLEN, + range_end_rtx - *rtx + 1); + return 0; + } + + *rtx = range_end_rtx + 1; + } + + return 0; +} |