Skip to content

Commit 758303d

Browse files
author
Darrick J. Wong
committed
xfs: flush eof/cowblocks if we can't reserve quota for chown
If a file user, group, or project change is unable to reserve enough quota to handle the modification, try clearing whatever space the filesystem might have been hanging onto in the hopes of speeding up the filesystem. The flushing behavior will become particularly important when we add deferred inode inactivation because that will increase the amount of space that isn't actively tied to user data. Signed-off-by: Darrick J. Wong <djwong@kernel.org> Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Brian Foster <bfoster@redhat.com>
1 parent c237dd7 commit 758303d

File tree

1 file changed

+19
-10
lines changed

1 file changed

+19
-10
lines changed

fs/xfs/xfs_trans.c

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1138,16 +1138,21 @@ xfs_trans_alloc_icreate(
11381138
int
11391139
xfs_trans_alloc_ichange(
11401140
struct xfs_inode *ip,
1141-
struct xfs_dquot *udqp,
1142-
struct xfs_dquot *gdqp,
1143-
struct xfs_dquot *pdqp,
1141+
struct xfs_dquot *new_udqp,
1142+
struct xfs_dquot *new_gdqp,
1143+
struct xfs_dquot *new_pdqp,
11441144
bool force,
11451145
struct xfs_trans **tpp)
11461146
{
11471147
struct xfs_trans *tp;
11481148
struct xfs_mount *mp = ip->i_mount;
1149+
struct xfs_dquot *udqp;
1150+
struct xfs_dquot *gdqp;
1151+
struct xfs_dquot *pdqp;
1152+
bool retried = false;
11491153
int error;
11501154

1155+
retry:
11511156
error = xfs_trans_alloc(mp, &M_RES(mp)->tr_ichange, 0, 0, 0, &tp);
11521157
if (error)
11531158
return error;
@@ -1165,14 +1170,12 @@ xfs_trans_alloc_ichange(
11651170
/*
11661171
* For each quota type, skip quota reservations if the inode's dquots
11671172
* now match the ones that came from the caller, or the caller didn't
1168-
* pass one in.
1173+
* pass one in. The inode's dquots can change if we drop the ILOCK to
1174+
* perform a blockgc scan, so we must preserve the caller's arguments.
11691175
*/
1170-
if (udqp == ip->i_udquot)
1171-
udqp = NULL;
1172-
if (gdqp == ip->i_gdquot)
1173-
gdqp = NULL;
1174-
if (pdqp == ip->i_pdquot)
1175-
pdqp = NULL;
1176+
udqp = (new_udqp != ip->i_udquot) ? new_udqp : NULL;
1177+
gdqp = (new_gdqp != ip->i_gdquot) ? new_gdqp : NULL;
1178+
pdqp = (new_pdqp != ip->i_pdquot) ? new_pdqp : NULL;
11761179
if (udqp || gdqp || pdqp) {
11771180
unsigned int qflags = XFS_QMOPT_RES_REGBLKS;
11781181

@@ -1188,6 +1191,12 @@ xfs_trans_alloc_ichange(
11881191
error = xfs_trans_reserve_quota_bydquots(tp, mp, udqp, gdqp,
11891192
pdqp, ip->i_d.di_nblocks + ip->i_delayed_blks,
11901193
1, qflags);
1194+
if ((error == -EDQUOT || error == -ENOSPC) && !retried) {
1195+
xfs_trans_cancel(tp);
1196+
xfs_blockgc_free_dquots(mp, udqp, gdqp, pdqp, 0);
1197+
retried = true;
1198+
goto retry;
1199+
}
11911200
if (error)
11921201
goto out_cancel;
11931202
}

0 commit comments

Comments
 (0)