summaryrefslogtreecommitdiffstats
path: root/fs/xfs/libxfs
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2017-01-09 16:39:35 -0500
committerDarrick J. Wong <darrick.wong@oracle.com>2017-01-09 16:45:01 -0500
commit12ef830198b0d71668eb9b59f9ba69d32951a48a (patch)
tree8bec19b1d0a549562dc63251a94b1e1ddbb790b0 /fs/xfs/libxfs
parent54fee133ad59c87ab01dd84ab3e9397134b32acb (diff)
xfs: don't rely on ->total in xfs_alloc_space_available
->total is a bit of an odd parameter passed down to the low-level allocator all the way from the high-level callers. It's supposed to contain the maximum number of blocks to be allocated for the whole transaction [1]. But in xfs_iomap_write_allocate we only convert existing delayed allocations and thus only have a minimal block reservation for the current transaction, so xfs_alloc_space_available can't use it for the allocation decisions. Use the maximum of args->total and the calculated block requirement to make a decision. We probably should get rid of args->total eventually and instead apply ->minleft more broadly, but that will require some extensive changes all over. [1] which creates lots of confusion as most callers don't decrement it once doing a first allocation. But that's for a separate series. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Brian Foster <bfoster@redhat.com> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Diffstat (limited to 'fs/xfs/libxfs')
-rw-r--r--fs/xfs/libxfs/xfs_alloc.c7
1 files changed, 4 insertions, 3 deletions
diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c
index f2e7eb6e5243..9f06a211e157 100644
--- a/fs/xfs/libxfs/xfs_alloc.c
+++ b/fs/xfs/libxfs/xfs_alloc.c
@@ -1995,7 +1995,7 @@ xfs_alloc_space_available(
1995 int flags) 1995 int flags)
1996{ 1996{
1997 struct xfs_perag *pag = args->pag; 1997 struct xfs_perag *pag = args->pag;
1998 xfs_extlen_t longest; 1998 xfs_extlen_t alloc_len, longest;
1999 xfs_extlen_t reservation; /* blocks that are still reserved */ 1999 xfs_extlen_t reservation; /* blocks that are still reserved */
2000 int available; 2000 int available;
2001 2001
@@ -2005,15 +2005,16 @@ xfs_alloc_space_available(
2005 reservation = xfs_ag_resv_needed(pag, args->resv); 2005 reservation = xfs_ag_resv_needed(pag, args->resv);
2006 2006
2007 /* do we have enough contiguous free space for the allocation? */ 2007 /* do we have enough contiguous free space for the allocation? */
2008 alloc_len = args->minlen + (args->alignment - 1) + args->minalignslop;
2008 longest = xfs_alloc_longest_free_extent(args->mp, pag, min_free, 2009 longest = xfs_alloc_longest_free_extent(args->mp, pag, min_free,
2009 reservation); 2010 reservation);
2010 if ((args->minlen + args->alignment + args->minalignslop - 1) > longest) 2011 if (longest < alloc_len)
2011 return false; 2012 return false;
2012 2013
2013 /* do we have enough free space remaining for the allocation? */ 2014 /* do we have enough free space remaining for the allocation? */
2014 available = (int)(pag->pagf_freeblks + pag->pagf_flcount - 2015 available = (int)(pag->pagf_freeblks + pag->pagf_flcount -
2015 reservation - min_free - args->minleft); 2016 reservation - min_free - args->minleft);
2016 if (available < (int)args->total) 2017 if (available < (int)max(args->total, alloc_len))
2017 return false; 2018 return false;
2018 2019
2019 /* 2020 /*