All of lore.kernel.org
 help / color / mirror / Atom feed
From: Christoph Hellwig <hch@infradead.org>
To: xfs@oss.sgi.com
Subject: [PATCH 10/13] xfs: add CRC checks to the AGFL
Date: Tue, 10 Feb 2009 15:22:51 -0500	[thread overview]
Message-ID: <20090210202941.150266000@bombadil.infradead.org> (raw)
In-Reply-To: 20090210202241.546501000@bombadil.infradead.org

[-- Attachment #1: xfs-agfl-crc --]
[-- Type: text/plain, Size: 8422 bytes --]

Add CRC checks, location information and a magic number to the AGFL.
Previously the AGFL was just a block containing nothing but the
free block pointers.  The new AGFL has a real header with the usual
boilerplate instead, so that we can verify it's not corrupted and
written into the right place.


Signed-off-by: Christoph Hellwig <hch@lst.de>

Index: xfs/fs/xfs/xfs_ag.h
===================================================================
--- xfs.orig/fs/xfs/xfs_ag.h	2009-02-09 19:15:48.966944136 +0100
+++ xfs/fs/xfs/xfs_ag.h	2009-02-09 19:15:51.063944366 +0100
@@ -30,6 +30,7 @@ struct xfs_trans;
 
 #define	XFS_AGF_MAGIC	0x58414746	/* 'XAGF' */
 #define	XFS_AGI_MAGIC	0x58414749	/* 'XAGI' */
+#define	XFS_AGFL_MAGIC	0x5841464c	/* 'XAFL' */
 #define	XFS_AGF_VERSION	1
 #define	XFS_AGI_VERSION	1
 
@@ -162,13 +163,31 @@ extern int xfs_read_agi(struct xfs_mount
  */
 #define XFS_AGFL_DADDR(mp)	((xfs_daddr_t)(3 << (mp)->m_sectbb_log))
 #define	XFS_AGFL_BLOCK(mp)	XFS_HDR_BLOCK(mp, XFS_AGFL_DADDR(mp))
-#define XFS_AGFL_SIZE(mp)	((mp)->m_sb.sb_sectsize / sizeof(xfs_agblock_t))
 #define	XFS_BUF_TO_AGFL(bp)	((xfs_agfl_t *)XFS_BUF_PTR(bp))
 
+#define XFS_BUF_TO_AGFL_BNO(mp, bp) \
+	(xfs_sb_version_hascrc(&((mp)->m_sb)) ? \
+		&(XFS_BUF_TO_AGFL(bp)->agfl_bno[0]) : \
+		(__be32 *)XFS_BUF_PTR(bp))
+
+/*
+ * Size of the AGFL.  For CRC-enabled filesystes we steal the last two slots
+ * for location information (agno) and the crc.
+ */
+#define XFS_AGFL_SIZE(mp) \
+	((mp)->m_sb.sb_sectsize / sizeof(xfs_agblock_t) - \
+	 (xfs_sb_version_hascrc(&((mp)->m_sb)) ? sizeof(struct xfs_agfl) : 0))
+
 typedef struct xfs_agfl {
-	__be32		agfl_bno[1];	/* actually XFS_AGFL_SIZE(mp) */
+	__be32		agfl_magicnum;
+	__be32		agfl_seqno;
+	uuid_t		agfl_uuid;
+	__be32		agfl_crc;
+	__be32		agfl_bno[];	/* actually XFS_AGFL_SIZE(mp) */
 } xfs_agfl_t;
 
+extern void xfs_agfl_calc_crc(struct xfs_buf *bp);
+
 /*
  * Busy block/extent entry.  Used in perag to mark blocks that have been freed
  * but whose transactions aren't committed to disk yet.
Index: xfs/fs/xfs/xfs_alloc.c
===================================================================
--- xfs.orig/fs/xfs/xfs_alloc.c	2009-02-09 19:15:46.920944300 +0100
+++ xfs/fs/xfs/xfs_alloc.c	2009-02-09 19:15:51.064977738 +0100
@@ -472,6 +472,27 @@ xfs_alloc_fixup_trees(
 	return 0;
 }
 
+#define xfs_buf_verify_cksum(bp, offset) \
+	xfs_verify_cksum(XFS_BUF_PTR(bp), XFS_BUF_SIZE(bp), offset)
+#define xfs_buf_update_cksum(bp, offset) \
+	xfs_update_cksum(XFS_BUF_PTR(bp), XFS_BUF_SIZE(bp), offset)
+
+/*
+ * Calculate CRC on AGFL and stuff it into the structure.
+ *
+ * We CRC the entire AGFL sector, not just the bits we use so that changes
+ * in structure size as features are included do not invalidate CRCs.
+ *
+ * We get called here just before the AGFL is written to disk. We should
+ * also do some validity checking here.
+ */
+void
+xfs_agfl_calc_crc(
+	struct xfs_buf		*bp)
+{
+	xfs_buf_update_cksum(bp, offsetof(struct xfs_agfl, agfl_crc));
+}
+
 /*
  * Read in the allocation group free block array.
  */
@@ -494,8 +515,31 @@ xfs_alloc_read_agfl(
 		return error;
 	ASSERT(bp);
 	ASSERT(!XFS_BUF_GETERROR(bp));
+
+	/*
+	 * Validate the CRC of the AGF block only if the block is clean (i.e.
+	 * it just came from disk) and we have CRCs enabled.
+	 */
+	if (xfs_sb_version_hascrc(&mp->m_sb) &&
+	    !(XFS_BUF_ISWRITE(bp) || XFS_BUF_ISDELAYWRITE(bp))) {
+		struct xfs_agfl		*agfl = XFS_BUF_TO_AGFL(bp);
+
+		if (!xfs_buf_verify_cksum(bp, offsetof(xfs_agfl_t, agfl_crc)) ||
+		    !uuid_equal(&agfl->agfl_uuid, &mp->m_sb.sb_uuid) ||
+		    be32_to_cpu(agfl->agfl_magicnum) != XFS_AGFL_MAGIC ||
+		    be32_to_cpu(agfl->agfl_seqno) != agno) {
+			XFS_CORRUPTION_ERROR("xfs_read_agfl crc",
+					XFS_ERRLEVEL_LOW, mp, agfl);
+			xfs_trans_brelse(tp, bp);
+			return XFS_ERROR(EFSCORRUPTED);
+		}
+
+		xfs_buf_set_io_callback(bp, xfs_agfl_calc_crc);
+	}
+
 	XFS_BUF_SET_VTYPE_REF(bp, B_FS_AGFL, XFS_AGFL_REF);
 	*bpp = bp;
+
 	return 0;
 }
 
@@ -2063,18 +2107,18 @@ xfs_alloc_get_freelist(
 	int		btreeblk) /* destination is a AGF btree */
 {
 	xfs_agf_t	*agf;	/* a.g. freespace structure */
-	xfs_agfl_t	*agfl;	/* a.g. freelist structure */
 	xfs_buf_t	*agflbp;/* buffer for a.g. freelist structure */
 	xfs_agblock_t	bno;	/* block number returned */
+	__be32		*agfl_bno;
 	int		error;
 	int		logflags;
-	xfs_mount_t	*mp;	/* mount structure */
+	xfs_mount_t	*mp = tp->t_mountp;
 	xfs_perag_t	*pag;	/* per allocation group data */
 
-	agf = XFS_BUF_TO_AGF(agbp);
 	/*
 	 * Freelist is empty, give up.
 	 */
+	agf = XFS_BUF_TO_AGF(agbp);
 	if (!agf->agf_flcount) {
 		*bnop = NULLAGBLOCK;
 		return 0;
@@ -2082,15 +2126,17 @@ xfs_alloc_get_freelist(
 	/*
 	 * Read the array of free blocks.
 	 */
-	mp = tp->t_mountp;
-	if ((error = xfs_alloc_read_agfl(mp, tp,
-			be32_to_cpu(agf->agf_seqno), &agflbp)))
+	error = xfs_alloc_read_agfl(mp, tp, be32_to_cpu(agf->agf_seqno),
+				    &agflbp);
+	if (error)
 		return error;
-	agfl = XFS_BUF_TO_AGFL(agflbp);
+
+
 	/*
 	 * Get the block number and update the data structures.
 	 */
-	bno = be32_to_cpu(agfl->agfl_bno[be32_to_cpu(agf->agf_flfirst)]);
+	agfl_bno = XFS_BUF_TO_AGFL_BNO(mp, agflbp);
+	bno = be32_to_cpu(agfl_bno[be32_to_cpu(agf->agf_flfirst)]);
 	be32_add_cpu(&agf->agf_flfirst, 1);
 	xfs_trans_brelse(tp, agflbp);
 	if (be32_to_cpu(agf->agf_flfirst) == XFS_AGFL_SIZE(mp))
@@ -2186,12 +2232,13 @@ xfs_alloc_put_freelist(
 	int			btreeblk) /* block came from a AGF btree */
 {
 	xfs_agf_t		*agf;	/* a.g. freespace structure */
-	xfs_agfl_t		*agfl;	/* a.g. free block array */
 	__be32			*blockp;/* pointer to array entry */
 	int			error;
 	int			logflags;
 	xfs_mount_t		*mp;	/* mount structure */
 	xfs_perag_t		*pag;	/* per allocation group data */
+	__be32			*agfl_bno;
+	int			startoff;
 
 	agf = XFS_BUF_TO_AGF(agbp);
 	mp = tp->t_mountp;
@@ -2199,7 +2246,6 @@ xfs_alloc_put_freelist(
 	if (!agflbp && (error = xfs_alloc_read_agfl(mp, tp,
 			be32_to_cpu(agf->agf_seqno), &agflbp)))
 		return error;
-	agfl = XFS_BUF_TO_AGFL(agflbp);
 	be32_add_cpu(&agf->agf_fllast, 1);
 	if (be32_to_cpu(agf->agf_fllast) == XFS_AGFL_SIZE(mp))
 		agf->agf_fllast = 0;
@@ -2219,14 +2265,17 @@ xfs_alloc_put_freelist(
 	xfs_alloc_log_agf(tp, agbp, logflags);
 
 	ASSERT(be32_to_cpu(agf->agf_flcount) <= XFS_AGFL_SIZE(mp));
-	blockp = &agfl->agfl_bno[be32_to_cpu(agf->agf_fllast)];
+
+	agfl_bno = XFS_BUF_TO_AGFL_BNO(mp, agflbp);
+	blockp = &agfl_bno[be32_to_cpu(agf->agf_fllast)];
 	*blockp = cpu_to_be32(bno);
+
 	TRACE_MODAGF(NULL, agf, logflags);
 	xfs_alloc_log_agf(tp, agbp, logflags);
-	xfs_trans_log_buf(tp, agflbp,
-		(int)((xfs_caddr_t)blockp - (xfs_caddr_t)agfl),
-		(int)((xfs_caddr_t)blockp - (xfs_caddr_t)agfl +
-			sizeof(xfs_agblock_t) - 1));
+
+	startoff = (char *)blockp - XFS_BUF_PTR(agflbp);
+	xfs_trans_log_buf(tp, agflbp, startoff,
+			  startoff + sizeof(xfs_agblock_t) - 1);
 	return 0;
 }
 
Index: xfs/fs/xfs/xfs_log_recover.c
===================================================================
--- xfs.orig/fs/xfs/xfs_log_recover.c	2009-02-09 19:15:48.970972860 +0100
+++ xfs/fs/xfs/xfs_log_recover.c	2009-02-09 19:15:51.066944119 +0100
@@ -1999,6 +1999,9 @@ xlog_recover_do_reg_buffer(
  	case XFS_AGI_MAGIC:
 		xfs_agi_calc_crc(bp);
 		break;
+ 	case XFS_AGFL_MAGIC:
+		xfs_agfl_calc_crc(bp);
+		break;
 	default:
 		break;
 	}
Index: xfs/fs/xfs/xfs_fsops.c
===================================================================
--- xfs.orig/fs/xfs/xfs_fsops.c	2009-02-09 19:15:48.966944136 +0100
+++ xfs/fs/xfs/xfs_fsops.c	2009-02-09 19:15:51.066944119 +0100
@@ -253,6 +253,30 @@ xfs_growfs_data_private(
 		if (error) {
 			goto error0;
 		}
+
+		/*
+		 * AGFL block.
+		 */
+		if (xfs_sb_version_hascrc(&mp->m_sb)) {
+			struct xfs_agfl		*agfl;
+
+			bp = xfs_buf_get(mp->m_ddev_targp,
+					  XFS_AG_DADDR(mp, agno,
+					  	       XFS_AGFL_DADDR(mp)),
+					  XFS_FSS_TO_BB(mp, 1), 0);
+			agfl = XFS_BUF_TO_AGFL(bp);
+
+			memset(agfl, 0, mp->m_sb.sb_sectsize);
+			agfl->agfl_magicnum = cpu_to_be32(XFS_AGFL_MAGIC);
+			agfl->agfl_seqno = cpu_to_be32(agno);
+			uuid_copy(&agfl->agfl_uuid, &mp->m_sb.sb_uuid);
+			xfs_buf_set_io_callback(bp, xfs_agfl_calc_crc);
+
+			error = xfs_bwrite(mp, bp);
+			if (error)
+				goto error0;
+		}
+
 		/*
 		 * BNO btree root block
 		 */

_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs

  parent reply	other threads:[~2009-02-10 20:30 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-02-10 20:22 [PATCH 00/13] Updated CRC patches Christoph Hellwig
2009-02-10 20:22 ` [PATCH 01/13] xfs: cleanup xlog_bread Christoph Hellwig
2009-02-10 20:22 ` [PATCH 02/13] xfs: remove m_litino Christoph Hellwig
2009-02-10 20:22 ` [PATCH 03/13] xfs: remove m_attroffset Christoph Hellwig
2009-02-10 20:22 ` [PATCH 04/13] xfs: take inode version into account in XFS_LITINO Christoph Hellwig
2009-02-10 20:22 ` [PATCH 05/13] xfs: add CRC infrastructure Christoph Hellwig
2009-02-12  6:10   ` Josef 'Jeff' Sipek
2009-02-10 20:22 ` [PATCH 06/13] xfs: add support for large btree blocks Christoph Hellwig
2009-02-10 20:22 ` [PATCH 07/13] xfs: add CRC checks to the superblock Christoph Hellwig
2009-02-10 20:22 ` [PATCH 08/13] xfs: add CRC checks to the AGF Christoph Hellwig
2009-02-10 20:22 ` [PATCH 09/13] xfs: add CRC checks to the AGI Christoph Hellwig
2009-02-10 20:22 ` Christoph Hellwig [this message]
2009-02-11  7:54   ` [PATCH 10/13] xfs: add CRC checks to the AGFL Dave Chinner
2009-02-15 18:23     ` Christoph Hellwig
2009-02-10 20:22 ` [PATCH 11/13] xfs: add CRC checks to the log Christoph Hellwig
2009-02-10 20:22 ` [PATCH 12/13] xfs: add version 3 inode format with CRCs Christoph Hellwig
2009-02-12  6:38   ` Josef 'Jeff' Sipek
2009-02-12 18:42     ` Eric Sandeen
2009-02-12 18:51       ` Christoph Hellwig
2009-02-10 20:22 ` [PATCH 13/13] xfs: add CRC checks for quota blocks Christoph Hellwig
2009-02-12  6:41   ` Josef 'Jeff' Sipek
2009-02-13 20:10     ` Christoph Hellwig

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20090210202941.150266000@bombadil.infradead.org \
    --to=hch@infradead.org \
    --cc=xfs@oss.sgi.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.