xfs: refactor loading quota inodes in the regular case

Create a helper function to load quota inodes in the case where the
dqtype and the sb quota inode fields correspond.  This is true for
nearly all the iget callsites in the quota code, except for when we're
switching the group and project quota inodes.  We'll need this in
subsequent patches to make the metadir handling less convoluted.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
Darrick J. Wong 2024-08-30 15:37:17 -07:00
parent 2ca7b9d7b8
commit 2c4162be6c
4 changed files with 80 additions and 35 deletions

View File

@ -1538,6 +1538,43 @@ xfs_qm_mount_quotas(
}
}
/*
* Load the inode for a given type of quota, assuming that the sb fields have
* been sorted out. This is not true when switching quota types on a V4
* filesystem, so do not use this function for that.
*
* Returns -ENOENT if the quota inode field is NULLFSINO; 0 and an inode on
* success; or a negative errno.
*/
int
xfs_qm_qino_load(
struct xfs_mount *mp,
xfs_dqtype_t type,
struct xfs_inode **ipp)
{
xfs_ino_t ino = NULLFSINO;
switch (type) {
case XFS_DQTYPE_USER:
ino = mp->m_sb.sb_uquotino;
break;
case XFS_DQTYPE_GROUP:
ino = mp->m_sb.sb_gquotino;
break;
case XFS_DQTYPE_PROJ:
ino = mp->m_sb.sb_pquotino;
break;
default:
ASSERT(0);
return -EFSCORRUPTED;
}
if (ino == NULLFSINO)
return -ENOENT;
return xfs_iget(mp, NULL, ino, 0, 0, ipp);
}
/*
* This is called after the superblock has been read in and we're ready to
* iget the quota inodes.
@ -1561,24 +1598,21 @@ xfs_qm_init_quotainos(
if (XFS_IS_UQUOTA_ON(mp) &&
mp->m_sb.sb_uquotino != NULLFSINO) {
ASSERT(mp->m_sb.sb_uquotino > 0);
error = xfs_iget(mp, NULL, mp->m_sb.sb_uquotino,
0, 0, &uip);
error = xfs_qm_qino_load(mp, XFS_DQTYPE_USER, &uip);
if (error)
return error;
}
if (XFS_IS_GQUOTA_ON(mp) &&
mp->m_sb.sb_gquotino != NULLFSINO) {
ASSERT(mp->m_sb.sb_gquotino > 0);
error = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino,
0, 0, &gip);
error = xfs_qm_qino_load(mp, XFS_DQTYPE_GROUP, &gip);
if (error)
goto error_rele;
}
if (XFS_IS_PQUOTA_ON(mp) &&
mp->m_sb.sb_pquotino != NULLFSINO) {
ASSERT(mp->m_sb.sb_pquotino > 0);
error = xfs_iget(mp, NULL, mp->m_sb.sb_pquotino,
0, 0, &pip);
error = xfs_qm_qino_load(mp, XFS_DQTYPE_PROJ, &pip);
if (error)
goto error_rele;
}

View File

@ -184,4 +184,7 @@ xfs_get_defquota(struct xfs_quotainfo *qi, xfs_dqtype_t type)
}
}
int xfs_qm_qino_load(struct xfs_mount *mp, xfs_dqtype_t type,
struct xfs_inode **ipp);
#endif /* __XFS_QM_H__ */

View File

@ -53,16 +53,15 @@ xfs_qm_scall_quotaoff(
STATIC int
xfs_qm_scall_trunc_qfile(
struct xfs_mount *mp,
xfs_ino_t ino)
xfs_dqtype_t type)
{
struct xfs_inode *ip;
struct xfs_trans *tp;
int error;
if (ino == NULLFSINO)
error = xfs_qm_qino_load(mp, type, &ip);
if (error == -ENOENT)
return 0;
error = xfs_iget(mp, NULL, ino, 0, 0, &ip);
if (error)
return error;
@ -113,17 +112,17 @@ xfs_qm_scall_trunc_qfiles(
}
if (flags & XFS_QMOPT_UQUOTA) {
error = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_uquotino);
error = xfs_qm_scall_trunc_qfile(mp, XFS_DQTYPE_USER);
if (error)
return error;
}
if (flags & XFS_QMOPT_GQUOTA) {
error = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_gquotino);
error = xfs_qm_scall_trunc_qfile(mp, XFS_DQTYPE_GROUP);
if (error)
return error;
}
if (flags & XFS_QMOPT_PQUOTA)
error = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_pquotino);
error = xfs_qm_scall_trunc_qfile(mp, XFS_DQTYPE_PROJ);
return error;
}

View File

@ -16,24 +16,25 @@
#include "xfs_qm.h"
static void
static int
xfs_qm_fill_state(
struct qc_type_state *tstate,
struct xfs_mount *mp,
struct xfs_inode *ip,
xfs_ino_t ino,
struct xfs_def_quota *defq)
xfs_dqtype_t type)
{
bool tempqip = false;
struct xfs_inode *ip;
struct xfs_def_quota *defq;
int error;
tstate->ino = ino;
if (!ip && ino == NULLFSINO)
return;
if (!ip) {
if (xfs_iget(mp, NULL, ino, 0, 0, &ip))
return;
tempqip = true;
error = xfs_qm_qino_load(mp, type, &ip);
if (error) {
tstate->ino = NULLFSINO;
return error != -ENOENT ? error : 0;
}
defq = xfs_get_defquota(mp->m_quotainfo, type);
tstate->ino = ip->i_ino;
tstate->flags |= QCI_SYSFILE;
tstate->blocks = ip->i_nblocks;
tstate->nextents = ip->i_df.if_nextents;
@ -43,8 +44,9 @@ xfs_qm_fill_state(
tstate->spc_warnlimit = 0;
tstate->ino_warnlimit = 0;
tstate->rt_spc_warnlimit = 0;
if (tempqip)
xfs_irele(ip);
xfs_irele(ip);
return 0;
}
/*
@ -56,8 +58,9 @@ xfs_fs_get_quota_state(
struct super_block *sb,
struct qc_state *state)
{
struct xfs_mount *mp = XFS_M(sb);
struct xfs_quotainfo *q = mp->m_quotainfo;
struct xfs_mount *mp = XFS_M(sb);
struct xfs_quotainfo *q = mp->m_quotainfo;
int error;
memset(state, 0, sizeof(*state));
if (!XFS_IS_QUOTA_ON(mp))
@ -76,12 +79,18 @@ xfs_fs_get_quota_state(
if (XFS_IS_PQUOTA_ENFORCED(mp))
state->s_state[PRJQUOTA].flags |= QCI_LIMITS_ENFORCED;
xfs_qm_fill_state(&state->s_state[USRQUOTA], mp, q->qi_uquotaip,
mp->m_sb.sb_uquotino, &q->qi_usr_default);
xfs_qm_fill_state(&state->s_state[GRPQUOTA], mp, q->qi_gquotaip,
mp->m_sb.sb_gquotino, &q->qi_grp_default);
xfs_qm_fill_state(&state->s_state[PRJQUOTA], mp, q->qi_pquotaip,
mp->m_sb.sb_pquotino, &q->qi_prj_default);
error = xfs_qm_fill_state(&state->s_state[USRQUOTA], mp,
XFS_DQTYPE_USER);
if (error)
return error;
error = xfs_qm_fill_state(&state->s_state[GRPQUOTA], mp,
XFS_DQTYPE_GROUP);
if (error)
return error;
error = xfs_qm_fill_state(&state->s_state[PRJQUOTA], mp,
XFS_DQTYPE_PROJ);
if (error)
return error;
return 0;
}