@@ -38,6 +38,7 @@
#include "xfs_buf_item.h"
#include "xfs_log.h"
#include "xfs_ag_resv.h"
+#include "xfs_bmap.h"
struct workqueue_struct *xfs_alloc_wq;
@@ -2058,6 +2059,7 @@ xfs_alloc_space_available(
struct xfs_perag *pag = args->pag;
xfs_extlen_t longest;
xfs_extlen_t reservation; /* blocks that are still reserved */
+ xfs_extlen_t indlen = 0;
int available;
if (flags & XFS_ALLOC_FLAG_FREEING)
@@ -2071,9 +2073,12 @@ xfs_alloc_space_available(
if ((args->minlen + args->alignment + args->minalignslop - 1) > longest)
return false;
+ if (xfs_alloc_is_userdata(args->datatype))
+ indlen = __xfs_bmap_worst_indlen(args->mp, max(args->minlen, args->maxlen));
+
/* do we have enough free space remaining for the allocation? */
available = (int)(pag->pagf_freeblks + pag->pagf_flcount -
- reservation - min_free - args->total);
+ reservation - min_free - indlen - args->total);
if (available < (int)args->minleft || available <= 0)
return false;
@@ -183,19 +183,16 @@ xfs_bmbt_update(
* Compute the worst-case number of indirect blocks that will be used
* for ip's delayed extent of length "len".
*/
-STATIC xfs_filblks_t
-xfs_bmap_worst_indlen(
- xfs_inode_t *ip, /* incore inode pointer */
+xfs_filblks_t
+__xfs_bmap_worst_indlen(
+ xfs_mount_t *mp, /* mount structure */
xfs_filblks_t len) /* delayed extent length */
{
int level; /* btree level number */
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];
@@ -222,6 +219,14 @@ xfs_bmap_worst_indlen(
return rval;
}
+STATIC xfs_filblks_t
+xfs_bmap_worst_indlen(
+ xfs_inode_t *ip, /* incore inode pointer */
+ xfs_filblks_t len) /* delayed extent length */
+{
+ return __xfs_bmap_worst_indlen(ip->i_mount, len);
+}
+
/*
* Calculate the default attribute fork offset for newly created inodes.
*/
@@ -263,4 +263,9 @@ int xfs_bmap_map_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops,
int xfs_bmap_unmap_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops,
struct xfs_inode *ip, struct xfs_bmbt_irec *imap);
+xfs_filblks_t
+__xfs_bmap_worst_indlen(
+ xfs_mount_t *mp, /* mount structure */
+ xfs_filblks_t len); /* delayed extent length */
+
#endif /* __XFS_BMAP_H__ */
We need to make sure that the indirect blocks (e.g. bmap btree blocks) can be allocated from the same AG [1] when comitting to an AG for a file data block allocation. To do that we calculate the worst possible indirect len and subtract that from the free space in the AG. I don't really like how this makes the space allocator call back into the bmap code (even if only for a trivial helper), but I can't think of a better idea. [1] strictly speaking the same AG or one with a higher AG number, but that is so incredibly hard to express that we settle for the same AG. Signed-off-by: Christoph Hellwig <hch@lst.de> --- fs/xfs/libxfs/xfs_alloc.c | 7 ++++++- fs/xfs/libxfs/xfs_bmap.c | 17 +++++++++++------ fs/xfs/libxfs/xfs_bmap.h | 5 +++++ 3 files changed, 22 insertions(+), 7 deletions(-)