diff options
author | Darrick J. Wong <darrick.wong@oracle.com> | 2017-01-09 10:38:40 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-01-12 05:39:40 -0500 |
commit | 2b7dae91a1341302077798ddc38e8bfd8a012cf1 (patch) | |
tree | 3812cc3166cad5a7af4b4a94b4b79b848bc244a0 /fs | |
parent | 49dc19915d3b0893a698a2d78f732beaff119a4d (diff) |
xfs: factor rmap btree size into the indlen calculations
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 <eguan@redhat.com>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
Cc: Christoph Hellwig <hch@lst.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/xfs/libxfs/xfs_bmap.c | 17 |
1 files changed, 15 insertions, 2 deletions
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index 5c3c4dd14735..00188f559c8d 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c | |||
@@ -49,6 +49,7 @@ | |||
49 | #include "xfs_rmap.h" | 49 | #include "xfs_rmap.h" |
50 | #include "xfs_ag_resv.h" | 50 | #include "xfs_ag_resv.h" |
51 | #include "xfs_refcount.h" | 51 | #include "xfs_refcount.h" |
52 | #include "xfs_rmap_btree.h" | ||
52 | 53 | ||
53 | 54 | ||
54 | kmem_zone_t *xfs_bmap_free_item_zone; | 55 | kmem_zone_t *xfs_bmap_free_item_zone; |
@@ -190,8 +191,12 @@ xfs_bmap_worst_indlen( | |||
190 | int maxrecs; /* maximum record count at this level */ | 191 | int maxrecs; /* maximum record count at this level */ |
191 | xfs_mount_t *mp; /* mount structure */ | 192 | xfs_mount_t *mp; /* mount structure */ |
192 | xfs_filblks_t rval; /* return value */ | 193 | xfs_filblks_t rval; /* return value */ |
194 | xfs_filblks_t orig_len; | ||
193 | 195 | ||
194 | mp = ip->i_mount; | 196 | mp = ip->i_mount; |
197 | |||
198 | /* Calculate the worst-case size of the bmbt. */ | ||
199 | orig_len = len; | ||
195 | maxrecs = mp->m_bmap_dmxr[0]; | 200 | maxrecs = mp->m_bmap_dmxr[0]; |
196 | for (level = 0, rval = 0; | 201 | for (level = 0, rval = 0; |
197 | level < XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK); | 202 | level < XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK); |
@@ -199,12 +204,20 @@ xfs_bmap_worst_indlen( | |||
199 | len += maxrecs - 1; | 204 | len += maxrecs - 1; |
200 | do_div(len, maxrecs); | 205 | do_div(len, maxrecs); |
201 | rval += len; | 206 | rval += len; |
202 | if (len == 1) | 207 | if (len == 1) { |
203 | return rval + XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) - | 208 | rval += XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) - |
204 | level - 1; | 209 | level - 1; |
210 | break; | ||
211 | } | ||
205 | if (level == 0) | 212 | if (level == 0) |
206 | maxrecs = mp->m_bmap_dmxr[1]; | 213 | maxrecs = mp->m_bmap_dmxr[1]; |
207 | } | 214 | } |
215 | |||
216 | /* Calculate the worst-case size of the rmapbt. */ | ||
217 | if (xfs_sb_version_hasrmapbt(&mp->m_sb)) | ||
218 | rval += 1 + xfs_rmapbt_calc_size(mp, orig_len) + | ||
219 | mp->m_rmap_maxlevels; | ||
220 | |||
208 | return rval; | 221 | return rval; |
209 | } | 222 | } |
210 | 223 | ||