mirror of
https://github.com/torvalds/linux.git
synced 2024-12-18 00:53:40 +00:00
xfs: keep quota directory inode loaded
In the same vein as the previous patch, there's no point in the metapath
scrub setup function doing a lookup on the quota metadir just so it can
validate that lookups work correctly. Instead, retain the quota
directory inode in memory for the lifetime of the mount so that we can
check this meaningfully.
Cc: <stable@vger.kernel.org> # v6.13-rc1
Fixes: 128a055291
("xfs: scrub quota file metapaths")
Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
parent
9b72800103
commit
e1d8602b6c
@ -171,23 +171,13 @@ static int
|
||||
xchk_setup_metapath_quotadir(
|
||||
struct xfs_scrub *sc)
|
||||
{
|
||||
struct xfs_trans *tp;
|
||||
struct xfs_inode *dp = NULL;
|
||||
int error;
|
||||
struct xfs_quotainfo *qi = sc->mp->m_quotainfo;
|
||||
|
||||
error = xfs_trans_alloc_empty(sc->mp, &tp);
|
||||
if (error)
|
||||
return error;
|
||||
if (!qi || !qi->qi_dirip)
|
||||
return -ENOENT;
|
||||
|
||||
error = xfs_dqinode_load_parent(tp, &dp);
|
||||
xfs_trans_cancel(tp);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
error = xchk_setup_metapath_scan(sc, sc->mp->m_metadirip,
|
||||
kasprintf(GFP_KERNEL, "quota"), dp);
|
||||
xfs_irele(dp);
|
||||
return error;
|
||||
return xchk_setup_metapath_scan(sc, sc->mp->m_metadirip,
|
||||
kstrdup("quota", GFP_KERNEL), qi->qi_dirip);
|
||||
}
|
||||
|
||||
/* Scan a quota inode under the /quota directory. */
|
||||
@ -197,10 +187,7 @@ xchk_setup_metapath_dqinode(
|
||||
xfs_dqtype_t type)
|
||||
{
|
||||
struct xfs_quotainfo *qi = sc->mp->m_quotainfo;
|
||||
struct xfs_trans *tp = NULL;
|
||||
struct xfs_inode *dp = NULL;
|
||||
struct xfs_inode *ip = NULL;
|
||||
int error;
|
||||
|
||||
if (!qi)
|
||||
return -ENOENT;
|
||||
@ -222,20 +209,8 @@ xchk_setup_metapath_dqinode(
|
||||
if (!ip)
|
||||
return -ENOENT;
|
||||
|
||||
error = xfs_trans_alloc_empty(sc->mp, &tp);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
error = xfs_dqinode_load_parent(tp, &dp);
|
||||
xfs_trans_cancel(tp);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
error = xchk_setup_metapath_scan(sc, dp,
|
||||
return xchk_setup_metapath_scan(sc, qi->qi_dirip,
|
||||
kstrdup(xfs_dqinode_path(type), GFP_KERNEL), ip);
|
||||
|
||||
xfs_irele(dp);
|
||||
return error;
|
||||
}
|
||||
#else
|
||||
# define xchk_setup_metapath_quotadir(...) (-ENOENT)
|
||||
|
@ -241,6 +241,10 @@ xfs_qm_destroy_quotainos(
|
||||
xfs_irele(qi->qi_pquotaip);
|
||||
qi->qi_pquotaip = NULL;
|
||||
}
|
||||
if (qi->qi_dirip) {
|
||||
xfs_irele(qi->qi_dirip);
|
||||
qi->qi_dirip = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -646,8 +650,7 @@ xfs_qm_init_timelimits(
|
||||
static int
|
||||
xfs_qm_load_metadir_qinos(
|
||||
struct xfs_mount *mp,
|
||||
struct xfs_quotainfo *qi,
|
||||
struct xfs_inode **dpp)
|
||||
struct xfs_quotainfo *qi)
|
||||
{
|
||||
struct xfs_trans *tp;
|
||||
int error;
|
||||
@ -656,7 +659,7 @@ xfs_qm_load_metadir_qinos(
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
error = xfs_dqinode_load_parent(tp, dpp);
|
||||
error = xfs_dqinode_load_parent(tp, &qi->qi_dirip);
|
||||
if (error == -ENOENT) {
|
||||
/* no quota dir directory, but we'll create one later */
|
||||
error = 0;
|
||||
@ -666,21 +669,21 @@ xfs_qm_load_metadir_qinos(
|
||||
goto out_trans;
|
||||
|
||||
if (XFS_IS_UQUOTA_ON(mp)) {
|
||||
error = xfs_dqinode_load(tp, *dpp, XFS_DQTYPE_USER,
|
||||
error = xfs_dqinode_load(tp, qi->qi_dirip, XFS_DQTYPE_USER,
|
||||
&qi->qi_uquotaip);
|
||||
if (error && error != -ENOENT)
|
||||
goto out_trans;
|
||||
}
|
||||
|
||||
if (XFS_IS_GQUOTA_ON(mp)) {
|
||||
error = xfs_dqinode_load(tp, *dpp, XFS_DQTYPE_GROUP,
|
||||
error = xfs_dqinode_load(tp, qi->qi_dirip, XFS_DQTYPE_GROUP,
|
||||
&qi->qi_gquotaip);
|
||||
if (error && error != -ENOENT)
|
||||
goto out_trans;
|
||||
}
|
||||
|
||||
if (XFS_IS_PQUOTA_ON(mp)) {
|
||||
error = xfs_dqinode_load(tp, *dpp, XFS_DQTYPE_PROJ,
|
||||
error = xfs_dqinode_load(tp, qi->qi_dirip, XFS_DQTYPE_PROJ,
|
||||
&qi->qi_pquotaip);
|
||||
if (error && error != -ENOENT)
|
||||
goto out_trans;
|
||||
@ -696,34 +699,33 @@ out_trans:
|
||||
STATIC int
|
||||
xfs_qm_create_metadir_qinos(
|
||||
struct xfs_mount *mp,
|
||||
struct xfs_quotainfo *qi,
|
||||
struct xfs_inode **dpp)
|
||||
struct xfs_quotainfo *qi)
|
||||
{
|
||||
int error;
|
||||
|
||||
if (!*dpp) {
|
||||
error = xfs_dqinode_mkdir_parent(mp, dpp);
|
||||
if (!qi->qi_dirip) {
|
||||
error = xfs_dqinode_mkdir_parent(mp, &qi->qi_dirip);
|
||||
if (error && error != -EEXIST)
|
||||
return error;
|
||||
}
|
||||
|
||||
if (XFS_IS_UQUOTA_ON(mp) && !qi->qi_uquotaip) {
|
||||
error = xfs_dqinode_metadir_create(*dpp, XFS_DQTYPE_USER,
|
||||
&qi->qi_uquotaip);
|
||||
error = xfs_dqinode_metadir_create(qi->qi_dirip,
|
||||
XFS_DQTYPE_USER, &qi->qi_uquotaip);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
|
||||
if (XFS_IS_GQUOTA_ON(mp) && !qi->qi_gquotaip) {
|
||||
error = xfs_dqinode_metadir_create(*dpp, XFS_DQTYPE_GROUP,
|
||||
&qi->qi_gquotaip);
|
||||
error = xfs_dqinode_metadir_create(qi->qi_dirip,
|
||||
XFS_DQTYPE_GROUP, &qi->qi_gquotaip);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
|
||||
if (XFS_IS_PQUOTA_ON(mp) && !qi->qi_pquotaip) {
|
||||
error = xfs_dqinode_metadir_create(*dpp, XFS_DQTYPE_PROJ,
|
||||
&qi->qi_pquotaip);
|
||||
error = xfs_dqinode_metadir_create(qi->qi_dirip,
|
||||
XFS_DQTYPE_PROJ, &qi->qi_pquotaip);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
@ -768,7 +770,6 @@ xfs_qm_init_metadir_qinos(
|
||||
struct xfs_mount *mp)
|
||||
{
|
||||
struct xfs_quotainfo *qi = mp->m_quotainfo;
|
||||
struct xfs_inode *dp = NULL;
|
||||
int error;
|
||||
|
||||
if (!xfs_has_quota(mp)) {
|
||||
@ -777,20 +778,22 @@ xfs_qm_init_metadir_qinos(
|
||||
return error;
|
||||
}
|
||||
|
||||
error = xfs_qm_load_metadir_qinos(mp, qi, &dp);
|
||||
error = xfs_qm_load_metadir_qinos(mp, qi);
|
||||
if (error)
|
||||
goto out_err;
|
||||
|
||||
error = xfs_qm_create_metadir_qinos(mp, qi, &dp);
|
||||
error = xfs_qm_create_metadir_qinos(mp, qi);
|
||||
if (error)
|
||||
goto out_err;
|
||||
|
||||
xfs_irele(dp);
|
||||
/* The only user of the quota dir inode is online fsck */
|
||||
#if !IS_ENABLED(CONFIG_XFS_ONLINE_SCRUB)
|
||||
xfs_irele(qi->qi_dirip);
|
||||
qi->qi_dirip = NULL;
|
||||
#endif
|
||||
return 0;
|
||||
out_err:
|
||||
xfs_qm_destroy_quotainos(mp->m_quotainfo);
|
||||
if (dp)
|
||||
xfs_irele(dp);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -55,6 +55,7 @@ struct xfs_quotainfo {
|
||||
struct xfs_inode *qi_uquotaip; /* user quota inode */
|
||||
struct xfs_inode *qi_gquotaip; /* group quota inode */
|
||||
struct xfs_inode *qi_pquotaip; /* project quota inode */
|
||||
struct xfs_inode *qi_dirip; /* quota metadir */
|
||||
struct list_lru qi_lru;
|
||||
int qi_dquots;
|
||||
struct mutex qi_quotaofflock;/* to serialize quotaoff */
|
||||
|
Loading…
Reference in New Issue
Block a user