diff options
author | Christoph Hellwig <hch@lst.de> | 2017-01-09 16:39:35 -0500 |
---|---|---|
committer | Darrick J. Wong <darrick.wong@oracle.com> | 2017-01-09 16:45:01 -0500 |
commit | 12ef830198b0d71668eb9b59f9ba69d32951a48a (patch) | |
tree | 8bec19b1d0a549562dc63251a94b1e1ddbb790b0 /fs/xfs/libxfs | |
parent | 54fee133ad59c87ab01dd84ab3e9397134b32acb (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.c | 7 |
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 | /* |