Commit 35dc55b9 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Chandan Babu R
Browse files

xfs: handle nimaps=0 from xfs_bmapi_write in xfs_alloc_file_space



If xfs_bmapi_write finds a delalloc extent at the requested range, it
tries to convert the entire delalloc extent to a real allocation.

But if the allocator cannot find a single free extent large enough to
cover the start block of the requested range, xfs_bmapi_write will
return 0 but leave *nimaps set to 0.

In that case we simply need to keep looping with the same startoffset_fsb
so that one of the following allocations will eventually reach the
requested range.

Note that this could affect any caller of xfs_bmapi_write that covers
an existing delayed allocation.  As far as I can tell we do not have
any other such caller, though - the regular writeback path uses
xfs_bmapi_convert_delalloc to convert delayed allocations to real ones,
and direct I/O invalidates the page cache first.

Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatar"Darrick J. Wong" <djwong@kernel.org>
Signed-off-by: default avatarChandan Babu R <chandanbabu@kernel.org>
parent 2b99e410
Loading
Loading
Loading
Loading
+13 −11
Original line number Diff line number Diff line
@@ -774,12 +774,10 @@ xfs_alloc_file_space(
{
	xfs_mount_t		*mp = ip->i_mount;
	xfs_off_t		count;
	xfs_filblks_t		allocated_fsb;
	xfs_filblks_t		allocatesize_fsb;
	xfs_extlen_t		extsz, temp;
	xfs_fileoff_t		startoffset_fsb;
	xfs_fileoff_t		endoffset_fsb;
	int			nimaps;
	int			rt;
	xfs_trans_t		*tp;
	xfs_bmbt_irec_t		imaps[1], *imapp;
@@ -802,7 +800,6 @@ xfs_alloc_file_space(

	count = len;
	imapp = &imaps[0];
	nimaps = 1;
	startoffset_fsb	= XFS_B_TO_FSBT(mp, offset);
	endoffset_fsb = XFS_B_TO_FSB(mp, offset + count);
	allocatesize_fsb = endoffset_fsb - startoffset_fsb;
@@ -813,6 +810,7 @@ xfs_alloc_file_space(
	while (allocatesize_fsb && !error) {
		xfs_fileoff_t	s, e;
		unsigned int	dblocks, rblocks, resblks;
		int		nimaps = 1;

		/*
		 * Determine space reservations for data/realtime.
@@ -878,15 +876,19 @@ xfs_alloc_file_space(
		if (error)
			break;

		allocated_fsb = imapp->br_blockcount;

		if (nimaps == 0) {
			error = -ENOSPC;
			break;
		/*
		 * If the allocator cannot find a single free extent large
		 * enough to cover the start block of the requested range,
		 * xfs_bmapi_write will return 0 but leave *nimaps set to 0.
		 *
		 * In that case we simply need to keep looping with the same
		 * startoffset_fsb so that one of the following allocations
		 * will eventually reach the requested range.
		 */
		if (nimaps) {
			startoffset_fsb += imapp->br_blockcount;
			allocatesize_fsb -= imapp->br_blockcount;
		}

		startoffset_fsb += allocated_fsb;
		allocatesize_fsb -= allocated_fsb;
	}

	return error;