Skip to content

Commit c237dd7

Browse files
author
Darrick J. Wong
committed
xfs: flush eof/cowblocks if we can't reserve quota for inode creation
If an inode creation 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 766aabd commit c237dd7

File tree

3 files changed

+49
-30
lines changed

3 files changed

+49
-30
lines changed

fs/xfs/xfs_icache.c

Lines changed: 38 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1646,64 +1646,72 @@ xfs_start_block_reaping(
16461646
}
16471647

16481648
/*
1649-
* Run cow/eofblocks scans on the quotas applicable to the inode. For inodes
1650-
* with multiple quotas, we don't know exactly which quota caused an allocation
1651-
* failure. We make a best effort by including each quota under low free space
1652-
* conditions (less than 1% free space) in the scan.
1649+
* Run cow/eofblocks scans on the supplied dquots. We don't know exactly which
1650+
* quota caused an allocation failure, so we make a best effort by including
1651+
* each quota under low free space conditions (less than 1% free space) in the
1652+
* scan.
16531653
*
16541654
* Callers must not hold any inode's ILOCK. If requesting a synchronous scan
16551655
* (XFS_EOF_FLAGS_SYNC), the caller also must not hold any inode's IOLOCK or
16561656
* MMAPLOCK.
16571657
*/
16581658
int
1659-
xfs_blockgc_free_quota(
1660-
struct xfs_inode *ip,
1659+
xfs_blockgc_free_dquots(
1660+
struct xfs_mount *mp,
1661+
struct xfs_dquot *udqp,
1662+
struct xfs_dquot *gdqp,
1663+
struct xfs_dquot *pdqp,
16611664
unsigned int eof_flags)
16621665
{
16631666
struct xfs_eofblocks eofb = {0};
1664-
struct xfs_dquot *dq;
16651667
bool do_work = false;
16661668
int error;
16671669

1670+
if (!udqp && !gdqp && !pdqp)
1671+
return 0;
1672+
16681673
/*
16691674
* Run a scan to free blocks using the union filter to cover all
16701675
* applicable quotas in a single scan.
16711676
*/
16721677
eofb.eof_flags = XFS_EOF_FLAGS_UNION | eof_flags;
16731678

1674-
if (XFS_IS_UQUOTA_ENFORCED(ip->i_mount)) {
1675-
dq = xfs_inode_dquot(ip, XFS_DQTYPE_USER);
1676-
if (dq && xfs_dquot_lowsp(dq)) {
1677-
eofb.eof_uid = VFS_I(ip)->i_uid;
1678-
eofb.eof_flags |= XFS_EOF_FLAGS_UID;
1679-
do_work = true;
1680-
}
1679+
if (XFS_IS_UQUOTA_ENFORCED(mp) && udqp && xfs_dquot_lowsp(udqp)) {
1680+
eofb.eof_uid = make_kuid(mp->m_super->s_user_ns, udqp->q_id);
1681+
eofb.eof_flags |= XFS_EOF_FLAGS_UID;
1682+
do_work = true;
16811683
}
16821684

1683-
if (XFS_IS_GQUOTA_ENFORCED(ip->i_mount)) {
1684-
dq = xfs_inode_dquot(ip, XFS_DQTYPE_GROUP);
1685-
if (dq && xfs_dquot_lowsp(dq)) {
1686-
eofb.eof_gid = VFS_I(ip)->i_gid;
1687-
eofb.eof_flags |= XFS_EOF_FLAGS_GID;
1688-
do_work = true;
1689-
}
1685+
if (XFS_IS_UQUOTA_ENFORCED(mp) && gdqp && xfs_dquot_lowsp(gdqp)) {
1686+
eofb.eof_gid = make_kgid(mp->m_super->s_user_ns, gdqp->q_id);
1687+
eofb.eof_flags |= XFS_EOF_FLAGS_GID;
1688+
do_work = true;
16901689
}
16911690

1692-
if (XFS_IS_PQUOTA_ENFORCED(ip->i_mount)) {
1693-
dq = xfs_inode_dquot(ip, XFS_DQTYPE_PROJ);
1694-
if (dq && xfs_dquot_lowsp(dq)) {
1695-
eofb.eof_prid = ip->i_d.di_projid;
1696-
eofb.eof_flags |= XFS_EOF_FLAGS_PRID;
1697-
do_work = true;
1698-
}
1691+
if (XFS_IS_PQUOTA_ENFORCED(mp) && pdqp && xfs_dquot_lowsp(pdqp)) {
1692+
eofb.eof_prid = pdqp->q_id;
1693+
eofb.eof_flags |= XFS_EOF_FLAGS_PRID;
1694+
do_work = true;
16991695
}
17001696

17011697
if (!do_work)
17021698
return 0;
17031699

1704-
error = xfs_icache_free_eofblocks(ip->i_mount, &eofb);
1700+
error = xfs_icache_free_eofblocks(mp, &eofb);
17051701
if (error)
17061702
return error;
17071703

1708-
return xfs_icache_free_cowblocks(ip->i_mount, &eofb);
1704+
return xfs_icache_free_cowblocks(mp, &eofb);
1705+
}
1706+
1707+
/* Run cow/eofblocks scans on the quotas attached to the inode. */
1708+
int
1709+
xfs_blockgc_free_quota(
1710+
struct xfs_inode *ip,
1711+
unsigned int eof_flags)
1712+
{
1713+
return xfs_blockgc_free_dquots(ip->i_mount,
1714+
xfs_inode_dquot(ip, XFS_DQTYPE_USER),
1715+
xfs_inode_dquot(ip, XFS_DQTYPE_GROUP),
1716+
xfs_inode_dquot(ip, XFS_DQTYPE_PROJ), eof_flags);
17091717
}

fs/xfs/xfs_icache.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ long xfs_reclaim_inodes_nr(struct xfs_mount *mp, int nr_to_scan);
5454

5555
void xfs_inode_set_reclaim_tag(struct xfs_inode *ip);
5656

57+
int xfs_blockgc_free_dquots(struct xfs_mount *mp, struct xfs_dquot *udqp,
58+
struct xfs_dquot *gdqp, struct xfs_dquot *pdqp,
59+
unsigned int eof_flags);
5760
int xfs_blockgc_free_quota(struct xfs_inode *ip, unsigned int eof_flags);
5861

5962
void xfs_inode_set_eofblocks_tag(struct xfs_inode *ip);

fs/xfs/xfs_trans.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1102,13 +1102,21 @@ xfs_trans_alloc_icreate(
11021102
struct xfs_trans **tpp)
11031103
{
11041104
struct xfs_trans *tp;
1105+
bool retried = false;
11051106
int error;
11061107

1108+
retry:
11071109
error = xfs_trans_alloc(mp, resv, dblocks, 0, 0, &tp);
11081110
if (error)
11091111
return error;
11101112

11111113
error = xfs_trans_reserve_quota_icreate(tp, udqp, gdqp, pdqp, dblocks);
1114+
if ((error == -EDQUOT || error == -ENOSPC) && !retried) {
1115+
xfs_trans_cancel(tp);
1116+
xfs_blockgc_free_dquots(mp, udqp, gdqp, pdqp, 0);
1117+
retried = true;
1118+
goto retry;
1119+
}
11121120
if (error) {
11131121
xfs_trans_cancel(tp);
11141122
return error;

0 commit comments

Comments
 (0)