Commit 83895227 authored by Darrick J. Wong's avatar Darrick J. Wong
Browse files

xfs: fix reflink quota reservation accounting error



Quota reservations are supposed to account for the blocks that might be
allocated due to a bmap btree split.  Reflink doesn't do this, so fix
this to make the quota accounting more accurate before we start
rearranging things.

Fixes: 862bb360 ("xfs: reflink extents from one file to another")
Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: default avatarBrian Foster <bfoster@redhat.com>
parent eb0efe50
Loading
Loading
Loading
Loading
+14 −7
Original line number Diff line number Diff line
@@ -1003,6 +1003,7 @@ xfs_reflink_remap_extent(
	xfs_filblks_t		rlen;
	xfs_filblks_t		unmap_len;
	xfs_off_t		newlen;
	int64_t			qres;
	int			error;

	unmap_len = irec->br_startoff + irec->br_blockcount - destoff;
@@ -1025,13 +1026,19 @@ xfs_reflink_remap_extent(
	xfs_ilock(ip, XFS_ILOCK_EXCL);
	xfs_trans_ijoin(tp, ip, 0);

	/* If we're not just clearing space, then do we have enough quota? */
	if (real_extent) {
		error = xfs_trans_reserve_quota_nblks(tp, ip,
				irec->br_blockcount, 0, XFS_QMOPT_RES_REGBLKS);
	/*
	 * Reserve quota for this operation.  We don't know if the first unmap
	 * in the dest file will cause a bmap btree split, so we always reserve
	 * at least enough blocks for that split.  If the extent being mapped
	 * in is written, we need to reserve quota for that too.
	 */
	qres = XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK);
	if (real_extent)
		qres += irec->br_blockcount;
	error = xfs_trans_reserve_quota_nblks(tp, ip, qres, 0,
			XFS_QMOPT_RES_REGBLKS);
	if (error)
		goto out_cancel;
	}

	trace_xfs_reflink_remap(ip, irec->br_startoff,
				irec->br_blockcount, irec->br_startblock);