[PATCH 1/5] xfs: buffer log item type mismatches are corruption

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Dave Chinner <dchinner@xxxxxxxxxx>

We detect when a buffer log format type and the magic number in the
buffer do not match. We issue a warning, but do not return an error
nor do we write back the recovered buffer. If no further recover
action is performed on that buffer, then recovery has left the
buffer in an inconsistent (out of date) state on disk. i.e. the
structure is corrupt on disk.

If this mismatch occurs, return a -EFSCORRUPTED error and cause
recovery to abort instead of letting recovery corrupt the filesystem
and continue onwards.

Signed-off-by: Dave Chinner <dchinner@xxxxxxxxxx>
---
 fs/xfs/xfs_buf_item_recover.c | 51 +++++++++++++++++------------------
 1 file changed, 24 insertions(+), 27 deletions(-)

diff --git a/fs/xfs/xfs_buf_item_recover.c b/fs/xfs/xfs_buf_item_recover.c
index d74bf7bb7794..dba57ee6fa6d 100644
--- a/fs/xfs/xfs_buf_item_recover.c
+++ b/fs/xfs/xfs_buf_item_recover.c
@@ -207,7 +207,7 @@ xlog_recover_buf_commit_pass1(
  *	the first 32 bits of the buffer (most blocks),
  *	inside a struct xfs_da_blkinfo at the start of the buffer.
  */
-static void
+static int
 xlog_recover_validate_buf_type(
 	struct xfs_mount		*mp,
 	struct xfs_buf			*bp,
@@ -407,11 +407,12 @@ xlog_recover_validate_buf_type(
 	 * skipped.
 	 */
 	if (current_lsn == NULLCOMMITLSN)
-		return;
+		return 0;;
 
 	if (warnmsg) {
 		xfs_warn(mp, warnmsg);
-		ASSERT(0);
+		xfs_buf_corruption_error(bp, __this_address);
+		return -EFSCORRUPTED;
 	}
 
 	/*
@@ -425,14 +426,11 @@ xlog_recover_validate_buf_type(
 	 * the buffer. Therefore, initialize a bli purely to carry the LSN to
 	 * the verifier.
 	 */
-	if (bp->b_ops) {
-		struct xfs_buf_log_item	*bip;
-
-		bp->b_flags |= _XBF_LOGRECOVERY;
-		xfs_buf_item_init(bp, mp);
-		bip = bp->b_log_item;
-		bip->bli_item.li_lsn = current_lsn;
-	}
+	ASSERT(bp->b_ops);
+	bp->b_flags |= _XBF_LOGRECOVERY;
+	xfs_buf_item_init(bp, mp);
+	bp->b_log_item->bli_item.li_lsn = current_lsn;
+	return 0;
 }
 
 /*
@@ -441,7 +439,7 @@ xlog_recover_validate_buf_type(
  * given buffer.  The bitmap in the buf log format structure indicates
  * where to place the logged data.
  */
-STATIC void
+static int
 xlog_recover_do_reg_buffer(
 	struct xfs_mount		*mp,
 	struct xlog_recover_item	*item,
@@ -523,20 +521,20 @@ xlog_recover_do_reg_buffer(
 	/* Shouldn't be any more regions */
 	ASSERT(i == item->ri_total);
 
-	xlog_recover_validate_buf_type(mp, bp, buf_f, current_lsn);
+	return xlog_recover_validate_buf_type(mp, bp, buf_f, current_lsn);
 }
 
 /*
- * Perform a dquot buffer recovery.
+ * Test if this dquot buffer item should be recovered.
  * Simple algorithm: if we have found a QUOTAOFF log item of the same type
  * (ie. USR or GRP), then just toss this buffer away; don't recover it.
  * Else, treat it as a regular buffer and do recovery.
  *
- * Return false if the buffer was tossed and true if we recovered the buffer to
- * indicate to the caller if the buffer needs writing.
+ * Return false if the buffer should be tossed and true if the buffer needs
+ * to be recovered.
  */
-STATIC bool
-xlog_recover_do_dquot_buffer(
+static bool
+xlog_recover_this_dquot_buffer(
 	struct xfs_mount		*mp,
 	struct xlog			*log,
 	struct xlog_recover_item	*item,
@@ -565,8 +563,6 @@ xlog_recover_do_dquot_buffer(
 	 */
 	if (log->l_quotaoffs_flag & type)
 		return false;
-
-	xlog_recover_do_reg_buffer(mp, item, bp, buf_f, NULLCOMMITLSN);
 	return true;
 }
 
@@ -952,18 +948,19 @@ xlog_recover_buf_commit_pass2(
 
 	if (buf_f->blf_flags & XFS_BLF_INODE_BUF) {
 		error = xlog_recover_do_inode_buffer(mp, item, bp, buf_f);
-		if (error)
-			goto out_release;
 	} else if (buf_f->blf_flags &
 		  (XFS_BLF_UDQUOT_BUF|XFS_BLF_PDQUOT_BUF|XFS_BLF_GDQUOT_BUF)) {
-		bool	dirty;
-
-		dirty = xlog_recover_do_dquot_buffer(mp, log, item, bp, buf_f);
-		if (!dirty)
+		if (!xlog_recover_this_dquot_buffer(mp, log, item, bp, buf_f))
 			goto out_release;
+
+		error = xlog_recover_do_reg_buffer(mp, item, bp, buf_f,
+				NULLCOMMITLSN);
 	} else {
-		xlog_recover_do_reg_buffer(mp, item, bp, buf_f, current_lsn);
+		error = xlog_recover_do_reg_buffer(mp, item, bp, buf_f,
+				current_lsn);
 	}
+	if (error)
+		goto out_release;
 
 	/*
 	 * Perform delayed write on the buffer.  Asynchronous writes will be
-- 
2.43.0





[Index of Archives]     [XFS Filesystem Development (older mail)]     [Linux Filesystem Development]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux RAID]     [Linux SCSI]


  Powered by Linux