]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
xfs: report quota block corruption errors to the health system
authorDarrick J. Wong <djwong@kernel.org>
Thu, 22 Feb 2024 20:32:44 +0000 (12:32 -0800)
committerDarrick J. Wong <djwong@kernel.org>
Thu, 22 Feb 2024 20:32:44 +0000 (12:32 -0800)
Whenever we encounter corrupt quota blocks, we should report that to the
health monitoring system for later reporting.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
fs/xfs/xfs_dquot.c
fs/xfs/xfs_health.c
fs/xfs/xfs_qm.c

index 308b5f33b712e5a3a4ca56537a763b6b61ccf249..30d36596a2e46aab1a58ffd058236a0585b699a2 100644 (file)
@@ -24,6 +24,7 @@
 #include "xfs_log.h"
 #include "xfs_bmap_btree.h"
 #include "xfs_error.h"
+#include "xfs_health.h"
 
 /*
  * Lock order:
@@ -44,6 +45,29 @@ static struct kmem_cache     *xfs_dquot_cache;
 static struct lock_class_key xfs_dquot_group_class;
 static struct lock_class_key xfs_dquot_project_class;
 
+/* Record observations of quota corruption with the health tracking system. */
+static void
+xfs_dquot_mark_sick(
+       struct xfs_dquot        *dqp)
+{
+       struct xfs_mount        *mp = dqp->q_mount;
+
+       switch (dqp->q_type) {
+       case XFS_DQTYPE_USER:
+               xfs_fs_mark_sick(mp, XFS_SICK_FS_UQUOTA);
+               break;
+       case XFS_DQTYPE_GROUP:
+               xfs_fs_mark_sick(mp, XFS_SICK_FS_GQUOTA);
+               break;
+       case XFS_DQTYPE_PROJ:
+               xfs_fs_mark_sick(mp, XFS_SICK_FS_PQUOTA);
+               break;
+       default:
+               ASSERT(0);
+               break;
+       }
+}
+
 /*
  * This is called to free all the memory associated with a dquot
  */
@@ -451,6 +475,8 @@ xfs_dquot_disk_read(
        error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp, dqp->q_blkno,
                        mp->m_quotainfo->qi_dqchunklen, 0, &bp,
                        &xfs_dquot_buf_ops);
+       if (xfs_metadata_is_sick(error))
+               xfs_dquot_mark_sick(dqp);
        if (error) {
                ASSERT(bp == NULL);
                return error;
@@ -574,6 +600,7 @@ xfs_dquot_from_disk(
                          "Metadata corruption detected at %pS, quota %u",
                          __this_address, dqp->q_id);
                xfs_alert(bp->b_mount, "Unmount and run xfs_repair");
+               xfs_dquot_mark_sick(dqp);
                return -EFSCORRUPTED;
        }
 
@@ -1238,6 +1265,8 @@ xfs_qm_dqflush(
                                   &bp, &xfs_dquot_buf_ops);
        if (error == -EAGAIN)
                goto out_unlock;
+       if (xfs_metadata_is_sick(error))
+               xfs_dquot_mark_sick(dqp);
        if (error)
                goto out_abort;
 
@@ -1246,6 +1275,7 @@ xfs_qm_dqflush(
                xfs_alert(mp, "corrupt dquot ID 0x%x in memory at %pS",
                                dqp->q_id, fa);
                xfs_buf_relse(bp);
+               xfs_dquot_mark_sick(dqp);
                error = -EFSCORRUPTED;
                goto out_abort;
        }
index 568300ae85550bfb78700f1ed4b1d3764863f015..bbdc621e5ee5c08d4d0df697d815f4a740e7cc78 100644 (file)
@@ -17,6 +17,7 @@
 #include "xfs_btree.h"
 #include "xfs_da_format.h"
 #include "xfs_da_btree.h"
+#include "xfs_quota_defs.h"
 
 /*
  * Warn about metadata corruption that we detected but haven't fixed, and
index 991be1eacb6c0d5ddcca8c24e9f94119e6309ac2..0f4cf4170c3578091d727b9dd36ba8dcbc89878f 100644 (file)
@@ -763,14 +763,18 @@ xfs_qm_qino_alloc(
                             (mp->m_sb.sb_gquotino != NULLFSINO)) {
                        ino = mp->m_sb.sb_gquotino;
                        if (XFS_IS_CORRUPT(mp,
-                                          mp->m_sb.sb_pquotino != NULLFSINO))
+                                          mp->m_sb.sb_pquotino != NULLFSINO)) {
+                               xfs_fs_mark_sick(mp, XFS_SICK_FS_PQUOTA);
                                return -EFSCORRUPTED;
+                       }
                } else if ((flags & XFS_QMOPT_GQUOTA) &&
                             (mp->m_sb.sb_pquotino != NULLFSINO)) {
                        ino = mp->m_sb.sb_pquotino;
                        if (XFS_IS_CORRUPT(mp,
-                                          mp->m_sb.sb_gquotino != NULLFSINO))
+                                          mp->m_sb.sb_gquotino != NULLFSINO)) {
+                               xfs_fs_mark_sick(mp, XFS_SICK_FS_GQUOTA);
                                return -EFSCORRUPTED;
+                       }
                }
                if (ino != NULLFSINO) {
                        error = xfs_iget(mp, NULL, ino, 0, 0, ipp);