]> www.infradead.org Git - users/hch/misc.git/commitdiff
xfs: keep quota directory inode loaded
authorDarrick J. Wong <djwong@kernel.org>
Mon, 2 Dec 2024 18:57:25 +0000 (10:57 -0800)
committerDarrick J. Wong <djwong@kernel.org>
Fri, 13 Dec 2024 01:45:08 +0000 (17:45 -0800)
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: 128a055291ebbc ("xfs: scrub quota file metapaths")
Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
fs/xfs/scrub/metapath.c
fs/xfs/xfs_qm.c
fs/xfs/xfs_qm.h

index 80467d6bc76389f717956c2775acbb6f3d836a71..c678cba1ffc3f7432d08d622ebe88c5d93cc628d 100644 (file)
@@ -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;
-
-       error = xfs_trans_alloc_empty(sc->mp, &tp);
-       if (error)
-               return error;
+       struct xfs_quotainfo    *qi = sc->mp->m_quotainfo;
 
-       error = xfs_dqinode_load_parent(tp, &dp);
-       xfs_trans_cancel(tp);
-       if (error)
-               return error;
+       if (!qi || !qi->qi_dirip)
+               return -ENOENT;
 
-       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)
index 61ee110b47d7dfe477ee40c6a9ab8e61f8531cac..3c0189831f14dd939a88543d5ce061ec2ad1322a 100644 (file)
@@ -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;
 }
 
index e919c7f62f5780260fe434c3b8de5bd57da35248..35b64bc3a7a8671e17c2bd89d82e82164e0cbb05 100644 (file)
@@ -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 */