|
@@ -248,7 +248,57 @@ xfs_qm_init_dquot_blk(
|
|
|
xfs_trans_log_buf(tp, bp, 0, BBTOB(q->qi_dqchunklen) - 1);
|
|
|
}
|
|
|
|
|
|
+static void
|
|
|
+xfs_dquot_buf_verify(
|
|
|
+ struct xfs_buf *bp)
|
|
|
+{
|
|
|
+ struct xfs_mount *mp = bp->b_target->bt_mount;
|
|
|
+ struct xfs_dqblk *d = (struct xfs_dqblk *)bp->b_addr;
|
|
|
+ struct xfs_disk_dquot *ddq;
|
|
|
+ xfs_dqid_t id = 0;
|
|
|
+ int i;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * On the first read of the buffer, verify that each dquot is valid.
|
|
|
+ * We don't know what the id of the dquot is supposed to be, just that
|
|
|
+ * they should be increasing monotonically within the buffer. If the
|
|
|
+ * first id is corrupt, then it will fail on the second dquot in the
|
|
|
+ * buffer so corruptions could point to the wrong dquot in this case.
|
|
|
+ */
|
|
|
+ for (i = 0; i < mp->m_quotainfo->qi_dqperchunk; i++) {
|
|
|
+ int error;
|
|
|
+
|
|
|
+ ddq = &d[i].dd_diskdq;
|
|
|
+
|
|
|
+ if (i == 0)
|
|
|
+ id = be32_to_cpu(ddq->d_id);
|
|
|
+
|
|
|
+ error = xfs_qm_dqcheck(mp, ddq, id + i, 0, XFS_QMOPT_DOWARN,
|
|
|
+ "xfs_dquot_read_verify");
|
|
|
+ if (error) {
|
|
|
+ XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, d);
|
|
|
+ xfs_buf_ioerror(bp, EFSCORRUPTED);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static void
|
|
|
+xfs_dquot_buf_write_verify(
|
|
|
+ struct xfs_buf *bp)
|
|
|
+{
|
|
|
+ xfs_dquot_buf_verify(bp);
|
|
|
+}
|
|
|
|
|
|
+void
|
|
|
+xfs_dquot_buf_read_verify(
|
|
|
+ struct xfs_buf *bp)
|
|
|
+{
|
|
|
+ xfs_dquot_buf_verify(bp);
|
|
|
+ bp->b_pre_io = xfs_dquot_buf_write_verify;
|
|
|
+ bp->b_iodone = NULL;
|
|
|
+ xfs_buf_ioend(bp, 0);
|
|
|
+}
|
|
|
|
|
|
/*
|
|
|
* Allocate a block and fill it with dquots.
|
|
@@ -315,6 +365,7 @@ xfs_qm_dqalloc(
|
|
|
error = xfs_buf_geterror(bp);
|
|
|
if (error)
|
|
|
goto error1;
|
|
|
+ bp->b_pre_io = xfs_dquot_buf_write_verify;
|
|
|
|
|
|
/*
|
|
|
* Make a chunk of dquots out of this buffer and log
|
|
@@ -359,59 +410,6 @@ xfs_qm_dqalloc(
|
|
|
|
|
|
return (error);
|
|
|
}
|
|
|
-
|
|
|
-static void
|
|
|
-xfs_dquot_buf_verify(
|
|
|
- struct xfs_buf *bp)
|
|
|
-{
|
|
|
- struct xfs_mount *mp = bp->b_target->bt_mount;
|
|
|
- struct xfs_dqblk *d = (struct xfs_dqblk *)bp->b_addr;
|
|
|
- struct xfs_disk_dquot *ddq;
|
|
|
- xfs_dqid_t id = 0;
|
|
|
- int i;
|
|
|
-
|
|
|
- /*
|
|
|
- * On the first read of the buffer, verify that each dquot is valid.
|
|
|
- * We don't know what the id of the dquot is supposed to be, just that
|
|
|
- * they should be increasing monotonically within the buffer. If the
|
|
|
- * first id is corrupt, then it will fail on the second dquot in the
|
|
|
- * buffer so corruptions could point to the wrong dquot in this case.
|
|
|
- */
|
|
|
- for (i = 0; i < mp->m_quotainfo->qi_dqperchunk; i++) {
|
|
|
- int error;
|
|
|
-
|
|
|
- ddq = &d[i].dd_diskdq;
|
|
|
-
|
|
|
- if (i == 0)
|
|
|
- id = be32_to_cpu(ddq->d_id);
|
|
|
-
|
|
|
- error = xfs_qm_dqcheck(mp, ddq, id + i, 0, XFS_QMOPT_DOWARN,
|
|
|
- "xfs_dquot_read_verify");
|
|
|
- if (error) {
|
|
|
- XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, d);
|
|
|
- xfs_buf_ioerror(bp, EFSCORRUPTED);
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-static void
|
|
|
-xfs_dquot_buf_write_verify(
|
|
|
- struct xfs_buf *bp)
|
|
|
-{
|
|
|
- xfs_dquot_buf_verify(bp);
|
|
|
-}
|
|
|
-
|
|
|
-void
|
|
|
-xfs_dquot_buf_read_verify(
|
|
|
- struct xfs_buf *bp)
|
|
|
-{
|
|
|
- xfs_dquot_buf_verify(bp);
|
|
|
- bp->b_pre_io = xfs_dquot_buf_write_verify;
|
|
|
- bp->b_iodone = NULL;
|
|
|
- xfs_buf_ioend(bp, 0);
|
|
|
-}
|
|
|
-
|
|
|
STATIC int
|
|
|
xfs_qm_dqrepair(
|
|
|
struct xfs_mount *mp,
|