2929#include "xfs_metafile.h"
3030#include "xfs_rtgroup.h"
3131#include "xfs_error.h"
32+ #include "xfs_trace.h"
3233
3334/*
3435 * Return whether there are any free extents in the size range given
@@ -1659,6 +1660,114 @@ xfs_rtalloc_align_minmax(
16591660 * raminlen = newminlen ;
16601661}
16611662
1663+ /* Given a free extent, find any part of it that isn't busy, if possible. */
1664+ STATIC bool
1665+ xfs_rtalloc_check_busy (
1666+ struct xfs_rtalloc_args * args ,
1667+ xfs_rtxnum_t start ,
1668+ xfs_rtxlen_t minlen_rtx ,
1669+ xfs_rtxlen_t maxlen_rtx ,
1670+ xfs_rtxlen_t len_rtx ,
1671+ xfs_rtxlen_t prod ,
1672+ xfs_rtxnum_t rtx ,
1673+ xfs_rtxlen_t * reslen ,
1674+ xfs_rtxnum_t * resrtx ,
1675+ unsigned * busy_gen )
1676+ {
1677+ struct xfs_rtgroup * rtg = args -> rtg ;
1678+ struct xfs_mount * mp = rtg_mount (rtg );
1679+ xfs_agblock_t rgbno = xfs_rtx_to_rgbno (rtg , rtx );
1680+ xfs_rgblock_t min_rgbno = xfs_rtx_to_rgbno (rtg , start );
1681+ xfs_extlen_t minlen = xfs_rtxlen_to_extlen (mp , minlen_rtx );
1682+ xfs_extlen_t len = xfs_rtxlen_to_extlen (mp , len_rtx );
1683+ xfs_extlen_t diff ;
1684+ bool busy ;
1685+
1686+ busy = xfs_extent_busy_trim (rtg_group (rtg ), minlen ,
1687+ xfs_rtxlen_to_extlen (mp , maxlen_rtx ), & rgbno , & len ,
1688+ busy_gen );
1689+
1690+ /*
1691+ * If we have a largish extent that happens to start before min_rgbno,
1692+ * see if we can shift it into range...
1693+ */
1694+ if (rgbno < min_rgbno && rgbno + len > min_rgbno ) {
1695+ diff = min_rgbno - rgbno ;
1696+ if (len > diff ) {
1697+ rgbno += diff ;
1698+ len -= diff ;
1699+ }
1700+ }
1701+
1702+ if (prod > 1 && len >= minlen ) {
1703+ xfs_rgblock_t aligned_rgbno = roundup (rgbno , prod );
1704+
1705+ diff = aligned_rgbno - rgbno ;
1706+
1707+ * resrtx = xfs_rgbno_to_rtx (mp , aligned_rgbno );
1708+ * reslen = xfs_extlen_to_rtxlen (mp ,
1709+ diff >= len ? 0 : len - diff );
1710+ } else {
1711+ * resrtx = xfs_rgbno_to_rtx (mp , rgbno );
1712+ * reslen = xfs_extlen_to_rtxlen (mp , len );
1713+ }
1714+
1715+ return busy ;
1716+ }
1717+
1718+ /*
1719+ * Adjust the given free extent so that it isn't busy, or flush the log and
1720+ * wait for the space to become unbusy. Only needed for rtgroups.
1721+ */
1722+ STATIC int
1723+ xfs_rtallocate_adjust_for_busy (
1724+ struct xfs_rtalloc_args * args ,
1725+ xfs_rtxnum_t start ,
1726+ xfs_rtxlen_t minlen ,
1727+ xfs_rtxlen_t maxlen ,
1728+ xfs_rtxlen_t * len ,
1729+ xfs_rtxlen_t prod ,
1730+ xfs_rtxnum_t * rtx )
1731+ {
1732+ xfs_rtxnum_t resrtx ;
1733+ xfs_rtxlen_t reslen ;
1734+ unsigned busy_gen ;
1735+ bool busy ;
1736+ int error ;
1737+
1738+ again :
1739+ busy = xfs_rtalloc_check_busy (args , start , minlen , maxlen , * len , prod ,
1740+ * rtx , & reslen , & resrtx , & busy_gen );
1741+ if (!busy )
1742+ return 0 ;
1743+
1744+ if (reslen < minlen || (start != 0 && resrtx != * rtx )) {
1745+ /*
1746+ * Enough of the extent was busy that we cannot satisfy the
1747+ * allocation, or this is a near allocation and the start of
1748+ * the extent is busy. Flush the log and wait for the busy
1749+ * situation to resolve.
1750+ */
1751+ trace_xfs_rtalloc_extent_busy (args -> rtg , start , minlen , maxlen ,
1752+ * len , prod , * rtx , busy_gen );
1753+
1754+ error = xfs_extent_busy_flush (args -> tp , rtg_group (args -> rtg ),
1755+ busy_gen , 0 );
1756+ if (error )
1757+ return error ;
1758+
1759+ goto again ;
1760+ }
1761+
1762+ /* Some of the free space wasn't busy, hand that back to the caller. */
1763+ trace_xfs_rtalloc_extent_busy_trim (args -> rtg , * rtx , * len , resrtx ,
1764+ reslen );
1765+ * len = reslen ;
1766+ * rtx = resrtx ;
1767+
1768+ return 0 ;
1769+ }
1770+
16621771static int
16631772xfs_rtallocate_rtg (
16641773 struct xfs_trans * tp ,
@@ -1740,15 +1849,19 @@ xfs_rtallocate_rtg(
17401849 }
17411850
17421851 if (error ) {
1743- if (xfs_has_rtgroups (args .mp )) {
1744- xfs_rtgroup_unlock (args .rtg , XFS_RTGLOCK_BITMAP );
1745- * rtlocked = false;
1746- }
1852+ if (xfs_has_rtgroups (args .mp ))
1853+ goto out_unlock ;
17471854 goto out_release ;
17481855 }
17491856
1750- if (xfs_has_rtgroups (args .mp ))
1857+ if (xfs_has_rtgroups (args .mp )) {
1858+ error = xfs_rtallocate_adjust_for_busy (& args , start , minlen ,
1859+ maxlen , & len , prod , & rtx );
1860+ if (error )
1861+ goto out_unlock ;
1862+
17511863 xfs_rtgroup_trans_join (tp , args .rtg , XFS_RTGLOCK_BITMAP );
1864+ }
17521865
17531866 error = xfs_rtallocate_range (& args , rtx , len );
17541867 if (error )
@@ -1764,6 +1877,10 @@ xfs_rtallocate_rtg(
17641877 xfs_rtgroup_rele (args .rtg );
17651878 xfs_rtbuf_cache_relse (& args );
17661879 return error ;
1880+ out_unlock :
1881+ xfs_rtgroup_unlock (args .rtg , XFS_RTGLOCK_BITMAP );
1882+ * rtlocked = false;
1883+ goto out_release ;
17671884}
17681885
17691886static int
0 commit comments