4.9-stable review patch.  If anyone has any objections, please let me know.

------------------


From: "Darrick J. Wong" <[email protected]>

commit fd26a88093bab6529ea2de819114ca92dbd1d71d upstream.

When we're estimating the amount of space it's going to take to satisfy
a delalloc reservation, we need to include the space that we might need
to grow the rmapbt.  This helps us to avoid running out of space later
when _iomap_write_allocate needs more space than we reserved.  Eryu Guan
observed this happening on generic/224 when sunit/swidth were set.

Reported-by: Eryu Guan <[email protected]>
Signed-off-by: Darrick J. Wong <[email protected]>
Reviewed-by: Dave Chinner <[email protected]>
Signed-off-by: Dave Chinner <[email protected]>
Cc: Christoph Hellwig <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
---
 fs/xfs/libxfs/xfs_bmap.c |   17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

--- a/fs/xfs/libxfs/xfs_bmap.c
+++ b/fs/xfs/libxfs/xfs_bmap.c
@@ -49,6 +49,7 @@
 #include "xfs_rmap.h"
 #include "xfs_ag_resv.h"
 #include "xfs_refcount.h"
+#include "xfs_rmap_btree.h"
 
 
 kmem_zone_t            *xfs_bmap_free_item_zone;
@@ -190,8 +191,12 @@ xfs_bmap_worst_indlen(
        int             maxrecs;        /* maximum record count at this level */
        xfs_mount_t     *mp;            /* mount structure */
        xfs_filblks_t   rval;           /* return value */
+       xfs_filblks_t   orig_len;
 
        mp = ip->i_mount;
+
+       /* Calculate the worst-case size of the bmbt. */
+       orig_len = len;
        maxrecs = mp->m_bmap_dmxr[0];
        for (level = 0, rval = 0;
             level < XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK);
@@ -199,12 +204,20 @@ xfs_bmap_worst_indlen(
                len += maxrecs - 1;
                do_div(len, maxrecs);
                rval += len;
-               if (len == 1)
-                       return rval + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) -
+               if (len == 1) {
+                       rval += XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) -
                                level - 1;
+                       break;
+               }
                if (level == 0)
                        maxrecs = mp->m_bmap_dmxr[1];
        }
+
+       /* Calculate the worst-case size of the rmapbt. */
+       if (xfs_sb_version_hasrmapbt(&mp->m_sb))
+               rval += 1 + xfs_rmapbt_calc_size(mp, orig_len) +
+                               mp->m_rmap_maxlevels;
+
        return rval;
 }
 


Reply via email to