Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ea562ed6 authored by Dave Chinner's avatar Dave Chinner Committed by Ben Myers
Browse files

xfs: fix delalloc quota accounting on failure



xfstest 270 was causing quota reservations way beyond what was sane
(ten to hundreds of TB) for a 4GB filesystem. There's a sign problem
in the error handling path of xfs_bmapi_reserve_delalloc() because
xfs_trans_unreserve_quota_nblks() simple negates the value passed -
which doesn't work for an unsigned variable. This causes
reservations of close to 2^32 block instead of removing a
reservation of a handful of blocks.

Fix the same problem in the other xfs_trans_unreserve_quota_nblks()
callers where unsigned integer variables are used, too.

Signed-off-by: default avatarDave Chinner <dchinner@redhat.com>
Reviewed-by: default avatarEric Sandeen <sandeen@redhat.com>
Signed-off-by: default avatarBen Myers <bpm@sgi.com>
parent 1307bbd2
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -4526,7 +4526,7 @@ xfs_bmapi_reserve_delalloc(
		xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS, alen, 0);
out_unreserve_quota:
	if (XFS_IS_QUOTA_ON(mp))
		xfs_trans_unreserve_quota_nblks(NULL, ip, alen, 0, rt ?
		xfs_trans_unreserve_quota_nblks(NULL, ip, (long)alen, 0, rt ?
				XFS_QMOPT_RES_RTBLKS : XFS_QMOPT_RES_REGBLKS);
	return error;
}
+1 −1
Original line number Diff line number Diff line
@@ -246,7 +246,7 @@ xfs_iomap_write_direct(

out_bmap_cancel:
	xfs_bmap_cancel(&free_list);
	xfs_trans_unreserve_quota_nblks(tp, ip, qblocks, 0, quota_flag);
	xfs_trans_unreserve_quota_nblks(tp, ip, (long)qblocks, 0, quota_flag);
out_trans_cancel:
	xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
	goto out_unlock;
+1 −1
Original line number Diff line number Diff line
@@ -1916,7 +1916,7 @@ xfs_alloc_file_space(

error0:	/* Cancel bmap, unlock inode, unreserve quota blocks, cancel trans */
	xfs_bmap_cancel(&free_list);
	xfs_trans_unreserve_quota_nblks(tp, ip, qblocks, 0, quota_flag);
	xfs_trans_unreserve_quota_nblks(tp, ip, (long)qblocks, 0, quota_flag);

error1:	/* Just cancel transaction */
	xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);