All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/13] Updated CRC patches
@ 2009-02-10 20:22 Christoph Hellwig
  2009-02-10 20:22 ` [PATCH 01/13] xfs: cleanup xlog_bread Christoph Hellwig
                   ` (12 more replies)
  0 siblings, 13 replies; 22+ messages in thread
From: Christoph Hellwig @ 2009-02-10 20:22 UTC (permalink / raw)
  To: xfs


This is an updated version of the CRC patches, against the current
development tree.  There are new patches for CRCs on the inode (including
a new version 3 inode format leaving space for other requested fields),
the AGFL (including a proper header for it) and quotas.

The log crc patch has been updated to properly deal with split logbuffers
and to checksum not only the log payload but also the log record header
and cycle data.

In general the kernel code should be pretty solid now, but the dir2 and
attr CRC support is still missing.  The inode crc patch will probably
get some sort of makeover after Dave's icreate transaction and the
reworked unlinked inode list handling go in.

The userspace support is available at:

	http://verein.lst.de/~hch/xfs/patches.xfsprogs.crc-20090210.tgz

and has gotten update for the new features, as well as support in xfs_db
for all the new fields.  It's not quite as solid as the kernel code yet,
we'll need another large libxfs resync and a solution to the different
uuid prototypes in userspace first.

There's a couple of new xfsqa failures with these patches, most are
due to different logprint output, or because the CRC catch xfs_db
induced corruptions in a different way than the old code would.
Some are because the new minimal inode size of 512 bytes confuse
various tests.

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

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 01/13] xfs: cleanup xlog_bread
  2009-02-10 20:22 [PATCH 00/13] Updated CRC patches Christoph Hellwig
@ 2009-02-10 20:22 ` Christoph Hellwig
  2009-02-10 20:22 ` [PATCH 02/13] xfs: remove m_litino Christoph Hellwig
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 22+ messages in thread
From: Christoph Hellwig @ 2009-02-10 20:22 UTC (permalink / raw)
  To: xfs

[-- Attachment #1: xfs-cleanup-xlog_bread --]
[-- Type: text/plain, Size: 13632 bytes --]

Most callers of xlog_bread need to call xlog_align to get the actual offset.
Consolidate that call into the main xlog_bread and provide a _xlog_bread
for those few that don't want the actual offset.


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

Index: xfs/fs/xfs/xfs_log_priv.h
===================================================================
--- xfs.orig/fs/xfs/xfs_log_priv.h	2009-02-10 19:16:19.308944151 +0100
+++ xfs/fs/xfs/xfs_log_priv.h	2009-02-10 19:22:43.915068626 +0100
@@ -455,7 +455,6 @@ extern void	 xlog_recover_process_iunlin
 
 extern struct xfs_buf *xlog_get_bp(xlog_t *, int);
 extern void	 xlog_put_bp(struct xfs_buf *);
-extern int	 xlog_bread(xlog_t *, xfs_daddr_t, int, struct xfs_buf *);
 
 extern kmem_zone_t	*xfs_log_ticket_zone;
 
Index: xfs/fs/xfs/xfs_log_recover.c
===================================================================
--- xfs.orig/fs/xfs/xfs_log_recover.c	2009-02-10 19:16:19.314973900 +0100
+++ xfs/fs/xfs/xfs_log_recover.c	2009-02-10 19:22:43.917068532 +0100
@@ -94,12 +94,30 @@ xlog_put_bp(
 	xfs_buf_free(bp);
 }
 
+STATIC xfs_caddr_t
+xlog_align(
+	xlog_t		*log,
+	xfs_daddr_t	blk_no,
+	int		nbblks,
+	xfs_buf_t	*bp)
+{
+	xfs_caddr_t	ptr;
+
+	if (!log->l_sectbb_log)
+		return XFS_BUF_PTR(bp);
+
+	ptr = XFS_BUF_PTR(bp) + BBTOB((int)blk_no & log->l_sectbb_mask);
+	ASSERT(XFS_BUF_SIZE(bp) >=
+		BBTOB(nbblks + (blk_no & log->l_sectbb_mask)));
+	return ptr;
+}
+
 
 /*
  * nbblks should be uint, but oh well.  Just want to catch that 32-bit length.
  */
-int
-xlog_bread(
+STATIC int
+_xlog_bread(
 	xlog_t		*log,
 	xfs_daddr_t	blk_no,
 	int		nbblks,
@@ -137,6 +155,24 @@ xlog_bread(
 	return error;
 }
 
+STATIC int
+xlog_bread(
+	xlog_t		*log,
+	xfs_daddr_t	blk_no,
+	int		nbblks,
+	xfs_buf_t	*bp,
+	xfs_caddr_t	*offset)
+{
+	int		error;
+
+	error = _xlog_bread(log, blk_no, nbblks, bp);
+	if (error)
+		return error;
+
+	*offset = xlog_align(log, blk_no, nbblks, bp);
+	return 0;
+}
+
 /*
  * Write out the buffer at the given block for the given number of blocks.
  * The buffer is kept locked across the write and is returned locked.
@@ -180,24 +216,6 @@ xlog_bwrite(
 	return error;
 }
 
-STATIC xfs_caddr_t
-xlog_align(
-	xlog_t		*log,
-	xfs_daddr_t	blk_no,
-	int		nbblks,
-	xfs_buf_t	*bp)
-{
-	xfs_caddr_t	ptr;
-
-	if (!log->l_sectbb_log)
-		return XFS_BUF_PTR(bp);
-
-	ptr = XFS_BUF_PTR(bp) + BBTOB((int)blk_no & log->l_sectbb_mask);
-	ASSERT(XFS_BUF_SIZE(bp) >=
-		BBTOB(nbblks + (blk_no & log->l_sectbb_mask)));
-	return ptr;
-}
-
 #ifdef DEBUG
 /*
  * dump debug superblock and log record information
@@ -321,9 +339,9 @@ xlog_find_cycle_start(
 
 	mid_blk = BLK_AVG(first_blk, *last_blk);
 	while (mid_blk != first_blk && mid_blk != *last_blk) {
-		if ((error = xlog_bread(log, mid_blk, 1, bp)))
+		error = xlog_bread(log, mid_blk, 1, bp, &offset);
+		if (error)
 			return error;
-		offset = xlog_align(log, mid_blk, 1, bp);
 		mid_cycle = xlog_get_cycle(offset);
 		if (mid_cycle == cycle) {
 			*last_blk = mid_blk;
@@ -379,10 +397,10 @@ xlog_find_verify_cycle(
 
 		bcount = min(bufblks, (start_blk + nbblks - i));
 
-		if ((error = xlog_bread(log, i, bcount, bp)))
+		error = xlog_bread(log, i, bcount, bp, &buf);
+		if (error)
 			goto out;
 
-		buf = xlog_align(log, i, bcount, bp);
 		for (j = 0; j < bcount; j++) {
 			cycle = xlog_get_cycle(buf);
 			if (cycle == stop_on_cycle_no) {
@@ -436,9 +454,9 @@ xlog_find_verify_log_record(
 			return ENOMEM;
 		smallmem = 1;
 	} else {
-		if ((error = xlog_bread(log, start_blk, num_blks, bp)))
+		error = xlog_bread(log, start_blk, num_blks, bp, &offset);
+		if (error)
 			goto out;
-		offset = xlog_align(log, start_blk, num_blks, bp);
 		offset += ((num_blks - 1) << BBSHIFT);
 	}
 
@@ -453,9 +471,9 @@ xlog_find_verify_log_record(
 		}
 
 		if (smallmem) {
-			if ((error = xlog_bread(log, i, 1, bp)))
+			error = xlog_bread(log, i, 1, bp, &offset);
+			if (error)
 				goto out;
-			offset = xlog_align(log, i, 1, bp);
 		}
 
 		head = (xlog_rec_header_t *)offset;
@@ -559,15 +577,18 @@ xlog_find_head(
 	bp = xlog_get_bp(log, 1);
 	if (!bp)
 		return ENOMEM;
-	if ((error = xlog_bread(log, 0, 1, bp)))
+
+	error = xlog_bread(log, 0, 1, bp, &offset);
+	if (error)
 		goto bp_err;
-	offset = xlog_align(log, 0, 1, bp);
+
 	first_half_cycle = xlog_get_cycle(offset);
 
 	last_blk = head_blk = log_bbnum - 1;	/* get cycle # of last block */
-	if ((error = xlog_bread(log, last_blk, 1, bp)))
+	error = xlog_bread(log, last_blk, 1, bp, &offset);
+	if (error)
 		goto bp_err;
-	offset = xlog_align(log, last_blk, 1, bp);
+
 	last_half_cycle = xlog_get_cycle(offset);
 	ASSERT(last_half_cycle != 0);
 
@@ -817,9 +838,10 @@ xlog_find_tail(
 	if (!bp)
 		return ENOMEM;
 	if (*head_blk == 0) {				/* special case */
-		if ((error = xlog_bread(log, 0, 1, bp)))
+		error = xlog_bread(log, 0, 1, bp, &offset);
+		if (error)
 			goto bread_err;
-		offset = xlog_align(log, 0, 1, bp);
+
 		if (xlog_get_cycle(offset) == 0) {
 			*tail_blk = 0;
 			/* leave all other log inited values alone */
@@ -832,9 +854,10 @@ xlog_find_tail(
 	 */
 	ASSERT(*head_blk < INT_MAX);
 	for (i = (int)(*head_blk) - 1; i >= 0; i--) {
-		if ((error = xlog_bread(log, i, 1, bp)))
+		error = xlog_bread(log, i, 1, bp, &offset);
+		if (error)
 			goto bread_err;
-		offset = xlog_align(log, i, 1, bp);
+
 		if (XLOG_HEADER_MAGIC_NUM == be32_to_cpu(*(__be32 *)offset)) {
 			found = 1;
 			break;
@@ -848,9 +871,10 @@ xlog_find_tail(
 	 */
 	if (!found) {
 		for (i = log->l_logBBsize - 1; i >= (int)(*head_blk); i--) {
-			if ((error = xlog_bread(log, i, 1, bp)))
+			error = xlog_bread(log, i, 1, bp, &offset);
+			if (error)
 				goto bread_err;
-			offset = xlog_align(log, i, 1, bp);
+
 			if (XLOG_HEADER_MAGIC_NUM ==
 			    be32_to_cpu(*(__be32 *)offset)) {
 				found = 2;
@@ -922,10 +946,10 @@ xlog_find_tail(
 	if (*head_blk == after_umount_blk &&
 	    be32_to_cpu(rhead->h_num_logops) == 1) {
 		umount_data_blk = (i + hblks) % log->l_logBBsize;
-		if ((error = xlog_bread(log, umount_data_blk, 1, bp))) {
+		error = xlog_bread(log, umount_data_blk, 1, bp, &offset);
+		if (error)
 			goto bread_err;
-		}
-		offset = xlog_align(log, umount_data_blk, 1, bp);
+
 		op_head = (xlog_op_header_t *)offset;
 		if (op_head->oh_flags & XLOG_UNMOUNT_TRANS) {
 			/*
@@ -1017,9 +1041,10 @@ xlog_find_zeroed(
 	bp = xlog_get_bp(log, 1);
 	if (!bp)
 		return ENOMEM;
-	if ((error = xlog_bread(log, 0, 1, bp)))
+	error = xlog_bread(log, 0, 1, bp, &offset);
+	if (error)
 		goto bp_err;
-	offset = xlog_align(log, 0, 1, bp);
+
 	first_cycle = xlog_get_cycle(offset);
 	if (first_cycle == 0) {		/* completely zeroed log */
 		*blk_no = 0;
@@ -1028,9 +1053,10 @@ xlog_find_zeroed(
 	}
 
 	/* check partially zeroed log */
-	if ((error = xlog_bread(log, log_bbnum-1, 1, bp)))
+	error = xlog_bread(log, log_bbnum-1, 1, bp, &offset);
+	if (error)
 		goto bp_err;
-	offset = xlog_align(log, log_bbnum-1, 1, bp);
+
 	last_cycle = xlog_get_cycle(offset);
 	if (last_cycle != 0) {		/* log completely written to */
 		xlog_put_bp(bp);
@@ -1152,10 +1178,10 @@ xlog_write_log_records(
 	 */
 	balign = XLOG_SECTOR_ROUNDDOWN_BLKNO(log, start_block);
 	if (balign != start_block) {
-		if ((error = xlog_bread(log, start_block, 1, bp))) {
-			xlog_put_bp(bp);
-			return error;
-		}
+		error = _xlog_bread(log, start_block, 1, bp);
+		if (error)
+			goto out_put_bp;
+
 		j = start_block - balign;
 	}
 
@@ -1175,10 +1201,14 @@ xlog_write_log_records(
 			balign = BBTOB(ealign - start_block);
 			error = XFS_BUF_SET_PTR(bp, offset + balign,
 						BBTOB(sectbb));
-			if (!error)
-				error = xlog_bread(log, ealign, sectbb, bp);
-			if (!error)
-				error = XFS_BUF_SET_PTR(bp, offset, bufblks);
+			if (error)
+				break;
+
+			error = _xlog_bread(log, ealign, sectbb, bp);
+			if (error)
+				break;
+
+			error = XFS_BUF_SET_PTR(bp, offset, bufblks);
 			if (error)
 				break;
 		}
@@ -1195,6 +1225,8 @@ xlog_write_log_records(
 		start_block += endcount;
 		j = 0;
 	}
+
+ out_put_bp:
 	xlog_put_bp(bp);
 	return error;
 }
@@ -3481,9 +3513,11 @@ xlog_do_recovery_pass(
 		hbp = xlog_get_bp(log, 1);
 		if (!hbp)
 			return ENOMEM;
-		if ((error = xlog_bread(log, tail_blk, 1, hbp)))
+
+		error = xlog_bread(log, tail_blk, 1, hbp, &offset);
+		if (error)
 			goto bread_err1;
-		offset = xlog_align(log, tail_blk, 1, hbp);
+
 		rhead = (xlog_rec_header_t *)offset;
 		error = xlog_valid_rec_header(log, rhead, tail_blk);
 		if (error)
@@ -3517,9 +3551,10 @@ xlog_do_recovery_pass(
 	memset(rhash, 0, sizeof(rhash));
 	if (tail_blk <= head_blk) {
 		for (blk_no = tail_blk; blk_no < head_blk; ) {
-			if ((error = xlog_bread(log, blk_no, hblks, hbp)))
+			error = xlog_bread(log, blk_no, hblks, hbp, &offset);
+			if (error)
 				goto bread_err2;
-			offset = xlog_align(log, blk_no, hblks, hbp);
+
 			rhead = (xlog_rec_header_t *)offset;
 			error = xlog_valid_rec_header(log, rhead, blk_no);
 			if (error)
@@ -3527,10 +3562,11 @@ xlog_do_recovery_pass(
 
 			/* blocks in data section */
 			bblks = (int)BTOBB(be32_to_cpu(rhead->h_len));
-			error = xlog_bread(log, blk_no + hblks, bblks, dbp);
+			error = xlog_bread(log, blk_no + hblks, bblks, dbp,
+					   &offset);
 			if (error)
 				goto bread_err2;
-			offset = xlog_align(log, blk_no + hblks, bblks, dbp);
+
 			xlog_unpack_data(rhead, offset, log);
 			if ((error = xlog_recover_process_data(log,
 						rhash, rhead, offset, pass)))
@@ -3553,10 +3589,10 @@ xlog_do_recovery_pass(
 			wrapped_hblks = 0;
 			if (blk_no + hblks <= log->l_logBBsize) {
 				/* Read header in one read */
-				error = xlog_bread(log, blk_no, hblks, hbp);
+				error = xlog_bread(log, blk_no, hblks, hbp,
+						   &offset);
 				if (error)
 					goto bread_err2;
-				offset = xlog_align(log, blk_no, hblks, hbp);
 			} else {
 				/* This LR is split across physical log end */
 				if (blk_no != log->l_logBBsize) {
@@ -3564,12 +3600,13 @@ xlog_do_recovery_pass(
 					ASSERT(blk_no <= INT_MAX);
 					split_hblks = log->l_logBBsize - (int)blk_no;
 					ASSERT(split_hblks > 0);
-					if ((error = xlog_bread(log, blk_no,
-							split_hblks, hbp)))
+					error = xlog_bread(log, blk_no,
+							   split_hblks, hbp,
+							   &offset);
+					if (error)
 						goto bread_err2;
-					offset = xlog_align(log, blk_no,
-							split_hblks, hbp);
 				}
+
 				/*
 				 * Note: this black magic still works with
 				 * large sector sizes (non-512) only because:
@@ -3587,14 +3624,18 @@ xlog_do_recovery_pass(
 				error = XFS_BUF_SET_PTR(hbp,
 						bufaddr + BBTOB(split_hblks),
 						BBTOB(hblks - split_hblks));
-				if (!error)
-					error = xlog_bread(log, 0,
-							wrapped_hblks, hbp);
-				if (!error)
-					error = XFS_BUF_SET_PTR(hbp, bufaddr,
+				if (error)
+					goto bread_err2;
+
+				error = _xlog_bread(log, 0, wrapped_hblks, hbp);
+				if (error)
+					goto bread_err2;
+
+				error = XFS_BUF_SET_PTR(hbp, bufaddr,
 							BBTOB(hblks));
 				if (error)
 					goto bread_err2;
+
 				if (!offset)
 					offset = xlog_align(log, 0,
 							wrapped_hblks, hbp);
@@ -3610,10 +3651,10 @@ xlog_do_recovery_pass(
 
 			/* Read in data for log record */
 			if (blk_no + bblks <= log->l_logBBsize) {
-				error = xlog_bread(log, blk_no, bblks, dbp);
+				error = xlog_bread(log, blk_no, bblks, dbp,
+						   &offset);
 				if (error)
 					goto bread_err2;
-				offset = xlog_align(log, blk_no, bblks, dbp);
 			} else {
 				/* This log record is split across the
 				 * physical end of log */
@@ -3627,12 +3668,13 @@ xlog_do_recovery_pass(
 					split_bblks =
 						log->l_logBBsize - (int)blk_no;
 					ASSERT(split_bblks > 0);
-					if ((error = xlog_bread(log, blk_no,
-							split_bblks, dbp)))
+					error = xlog_bread(log, blk_no,
+							split_bblks, dbp,
+							&offset);
+					if (error)
 						goto bread_err2;
-					offset = xlog_align(log, blk_no,
-							split_bblks, dbp);
 				}
+
 				/*
 				 * Note: this black magic still works with
 				 * large sector sizes (non-512) only because:
@@ -3649,15 +3691,19 @@ xlog_do_recovery_pass(
 				error = XFS_BUF_SET_PTR(dbp,
 						bufaddr + BBTOB(split_bblks),
 						BBTOB(bblks - split_bblks));
-				if (!error)
-					error = xlog_bread(log, wrapped_hblks,
-							bblks - split_bblks,
-							dbp);
-				if (!error)
-					error = XFS_BUF_SET_PTR(dbp, bufaddr,
-							h_size);
 				if (error)
 					goto bread_err2;
+
+				error = _xlog_bread(log, wrapped_hblks,
+						bblks - split_bblks,
+						dbp);
+				if (error)
+					goto bread_err2;
+
+				error = XFS_BUF_SET_PTR(dbp, bufaddr, h_size);
+				if (error)
+					goto bread_err2;
+
 				if (!offset)
 					offset = xlog_align(log, wrapped_hblks,
 						bblks - split_bblks, dbp);
@@ -3674,17 +3720,21 @@ xlog_do_recovery_pass(
 
 		/* read first part of physical log */
 		while (blk_no < head_blk) {
-			if ((error = xlog_bread(log, blk_no, hblks, hbp)))
+			error = xlog_bread(log, blk_no, hblks, hbp, &offset);
+			if (error)
 				goto bread_err2;
-			offset = xlog_align(log, blk_no, hblks, hbp);
+
 			rhead = (xlog_rec_header_t *)offset;
 			error = xlog_valid_rec_header(log, rhead, blk_no);
 			if (error)
 				goto bread_err2;
+
 			bblks = (int)BTOBB(be32_to_cpu(rhead->h_len));
-			if ((error = xlog_bread(log, blk_no+hblks, bblks, dbp)))
+			error = xlog_bread(log, blk_no+hblks, bblks, dbp,
+					   &offset);
+			if (error)
 				goto bread_err2;
-			offset = xlog_align(log, blk_no+hblks, bblks, dbp);
+
 			xlog_unpack_data(rhead, offset, log);
 			if ((error = xlog_recover_process_data(log, rhash,
 							rhead, offset, pass)))

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

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 02/13] xfs: remove m_litino
  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 ` Christoph Hellwig
  2009-02-10 20:22 ` [PATCH 03/13] xfs: remove m_attroffset Christoph Hellwig
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 22+ messages in thread
From: Christoph Hellwig @ 2009-02-10 20:22 UTC (permalink / raw)
  To: xfs

[-- Attachment #1: xfs-kill-m_litino --]
[-- Type: text/plain, Size: 2188 bytes --]

With the upcoming v3 inodes the inode data/attr area size needs to be
calculated for each specific inode, so we can't cache it in the superblock
anymore.


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

Index: xfs/fs/xfs/xfs_dinode.h
===================================================================
--- xfs.orig/fs/xfs/xfs_dinode.h	2009-02-09 19:15:18.816069935 +0100
+++ xfs/fs/xfs/xfs_dinode.h	2009-02-09 19:15:29.082068921 +0100
@@ -103,7 +103,9 @@ typedef enum xfs_dinode_fmt {
 /*
  * Inode size for given fs.
  */
-#define	XFS_LITINO(mp)	((mp)->m_litino)
+#define XFS_LITINO(mp) \
+	((int)(((mp)->m_sb.sb_inodesize) - sizeof(struct xfs_dinode)))
+
 #define	XFS_BROOT_SIZE_ADJ	\
 	(XFS_BTREE_LBLOCK_LEN - sizeof(xfs_bmdr_block_t))
 
Index: xfs/fs/xfs/xfs_mount.c
===================================================================
--- xfs.orig/fs/xfs/xfs_mount.c	2009-02-09 19:15:18.820068559 +0100
+++ xfs/fs/xfs/xfs_mount.c	2009-02-09 19:15:29.083069118 +0100
@@ -574,7 +574,6 @@ xfs_mount_common(xfs_mount_t *mp, xfs_sb
 	mp->m_sectbb_log = sbp->sb_sectlog - BBSHIFT;
 	mp->m_agno_log = xfs_highbit32(sbp->sb_agcount - 1) + 1;
 	mp->m_agino_log = sbp->sb_inopblog + sbp->sb_agblklog;
-	mp->m_litino = sbp->sb_inodesize - sizeof(struct xfs_dinode);
 	mp->m_blockmask = sbp->sb_blocksize - 1;
 	mp->m_blockwsize = sbp->sb_blocksize >> XFS_WORDLOG;
 	mp->m_blockwmask = mp->m_blockwsize - 1;
Index: xfs/fs/xfs/xfs_mount.h
===================================================================
--- xfs.orig/fs/xfs/xfs_mount.h	2009-02-09 19:15:18.826069182 +0100
+++ xfs/fs/xfs/xfs_mount.h	2009-02-09 19:15:29.084069385 +0100
@@ -281,7 +281,6 @@ typedef struct xfs_mount {
 	uint			m_attr_node_ents; /* #entries in attr danode */
 	int			m_ialloc_inos;	/* inodes in inode allocation */
 	int			m_ialloc_blks;	/* blocks in inode allocation */
-	int			m_litino;	/* size of inode union area */
 	int			m_inoalign_mask;/* mask sb_inoalignmt if used */
 	uint			m_qflags;	/* quota status flags */
 	xfs_trans_reservations_t m_reservations;/* precomputed res values */

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

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 03/13] xfs: remove m_attroffset
  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 ` Christoph Hellwig
  2009-02-10 20:22 ` [PATCH 04/13] xfs: take inode version into account in XFS_LITINO Christoph Hellwig
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 22+ messages in thread
From: Christoph Hellwig @ 2009-02-10 20:22 UTC (permalink / raw)
  To: xfs

[-- Attachment #1: xfs-xfs_default_attroffset --]
[-- Type: text/plain, Size: 6676 bytes --]

With the upcoming v3 inodes the default attroffset needs to be calculated
for each specific inode, so we can't cache it in the superblock anymore.

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

Index: xfs/fs/xfs/xfs_mount.c
===================================================================
--- xfs.orig/fs/xfs/xfs_mount.c	2009-02-09 19:15:29.083069118 +0100
+++ xfs/fs/xfs/xfs_mount.c	2009-02-09 19:15:35.578944518 +0100
@@ -566,6 +566,9 @@ xfs_readsb(xfs_mount_t *mp, int flags)
 STATIC void
 xfs_mount_common(xfs_mount_t *mp, xfs_sb_t *sbp)
 {
+	ASSERT(sbp->sb_inodesize ==  256 || sbp->sb_inodesize ==  512 ||
+	       sbp->sb_inodesize == 1024 || sbp->sb_inodesize == 2048);
+
 	mp->m_agfrotor = mp->m_agirotor = 0;
 	spin_lock_init(&mp->m_agirotor_lock);
 	mp->m_maxagi = mp->m_sb.sb_agcount;
@@ -578,27 +581,6 @@ xfs_mount_common(xfs_mount_t *mp, xfs_sb
 	mp->m_blockwsize = sbp->sb_blocksize >> XFS_WORDLOG;
 	mp->m_blockwmask = mp->m_blockwsize - 1;
 
-	/*
-	 * Setup for attributes, in case they get created.
-	 * This value is for inodes getting attributes for the first time,
-	 * the per-inode value is for old attribute values.
-	 */
-	ASSERT(sbp->sb_inodesize >= 256 && sbp->sb_inodesize <= 2048);
-	switch (sbp->sb_inodesize) {
-	case 256:
-		mp->m_attroffset = XFS_LITINO(mp) -
-				   XFS_BMDR_SPACE_CALC(MINABTPTRS);
-		break;
-	case 512:
-	case 1024:
-	case 2048:
-		mp->m_attroffset = XFS_BMDR_SPACE_CALC(6 * MINABTPTRS);
-		break;
-	default:
-		ASSERT(0);
-	}
-	ASSERT(mp->m_attroffset < XFS_LITINO(mp));
-
 	mp->m_alloc_mxr[0] = xfs_allocbt_maxrecs(mp, sbp->sb_blocksize, 1);
 	mp->m_alloc_mxr[1] = xfs_allocbt_maxrecs(mp, sbp->sb_blocksize, 0);
 	mp->m_alloc_mnr[0] = mp->m_alloc_mxr[0] / 2;
Index: xfs/fs/xfs/xfs_attr_leaf.c
===================================================================
--- xfs.orig/fs/xfs/xfs_attr_leaf.c	2009-02-09 19:15:18.754098923 +0100
+++ xfs/fs/xfs/xfs_attr_leaf.c	2009-02-09 19:15:35.580944493 +0100
@@ -155,7 +155,8 @@ xfs_attr_shortform_bytesfit(xfs_inode_t 
 		 * minimum offset only needs to be the space required for 
 		 * the btree root.
 		 */ 
-		if (!dp->i_d.di_forkoff && dp->i_df.if_bytes > mp->m_attroffset)
+		if (!dp->i_d.di_forkoff && dp->i_df.if_bytes >
+		    xfs_default_attroffset(dp))
 			dsize = XFS_BMDR_SPACE_CALC(MINDBTPTRS);
 		break;
 		
Index: xfs/fs/xfs/xfs_bmap.c
===================================================================
--- xfs.orig/fs/xfs/xfs_bmap.c	2009-02-09 19:15:18.758069609 +0100
+++ xfs/fs/xfs/xfs_bmap.c	2009-02-09 19:15:35.583944247 +0100
@@ -3577,6 +3577,27 @@ xfs_bmap_extents_to_btree(
 }
 
 /*
+ * Calculate the default attribute fork offset for newly created inodes.
+ */
+uint
+xfs_default_attroffset(
+	struct xfs_inode	*ip)
+{
+	struct xfs_mount	*mp = ip->i_mount;
+	uint			offset;
+
+	if (mp->m_sb.sb_inodesize == 256) {
+		offset = XFS_LITINO(mp) -
+				XFS_BMDR_SPACE_CALC(MINABTPTRS);
+	} else {
+		offset = XFS_BMDR_SPACE_CALC(6 * MINABTPTRS);
+	}
+
+	ASSERT(offset < XFS_LITINO(mp));
+	return offset;
+}
+
+/*
  * Helper routine to reset inode di_forkoff field when switching
  * attribute fork from local to extent format - we reset it where
  * possible to make space available for inline data fork extents.
@@ -3588,15 +3609,18 @@ xfs_bmap_forkoff_reset(
 	int		whichfork)
 {
 	if (whichfork == XFS_ATTR_FORK &&
-	    (ip->i_d.di_format != XFS_DINODE_FMT_DEV) &&
-	    (ip->i_d.di_format != XFS_DINODE_FMT_UUID) &&
-	    (ip->i_d.di_format != XFS_DINODE_FMT_BTREE) &&
-	    ((mp->m_attroffset >> 3) > ip->i_d.di_forkoff)) {
-		ip->i_d.di_forkoff = mp->m_attroffset >> 3;
-		ip->i_df.if_ext_max = XFS_IFORK_DSIZE(ip) /
-					(uint)sizeof(xfs_bmbt_rec_t);
-		ip->i_afp->if_ext_max = XFS_IFORK_ASIZE(ip) /
-					(uint)sizeof(xfs_bmbt_rec_t);
+	    ip->i_d.di_format != XFS_DINODE_FMT_DEV &&
+	    ip->i_d.di_format != XFS_DINODE_FMT_UUID &&
+	    ip->i_d.di_format != XFS_DINODE_FMT_BTREE) {
+		uint	dfl_forkoff = xfs_default_attroffset(ip) >> 3;
+
+		if (dfl_forkoff > ip->i_d.di_forkoff) {
+			ip->i_d.di_forkoff = dfl_forkoff;
+			ip->i_df.if_ext_max =
+				XFS_IFORK_DSIZE(ip) / sizeof(xfs_bmbt_rec_t);
+			ip->i_afp->if_ext_max =
+				XFS_IFORK_ASIZE(ip) / sizeof(xfs_bmbt_rec_t);
+		}
 	}
 }
 
@@ -4065,7 +4089,7 @@ xfs_bmap_add_attrfork(
 	case XFS_DINODE_FMT_BTREE:
 		ip->i_d.di_forkoff = xfs_attr_shortform_bytesfit(ip, size);
 		if (!ip->i_d.di_forkoff)
-			ip->i_d.di_forkoff = mp->m_attroffset >> 3;
+			ip->i_d.di_forkoff = xfs_default_attroffset(ip) >> 3;
 		else if (mp->m_flags & XFS_MOUNT_ATTR2)
 			version = 2;
 		break;
@@ -4212,12 +4236,12 @@ xfs_bmap_compute_maxlevels(
 	 * (a signed 16-bit number, xfs_aextnum_t).
 	 *
 	 * Note that we can no longer assume that if we are in ATTR1 that
-	 * the fork offset of all the inodes will be (m_attroffset >> 3)
-	 * because we could have mounted with ATTR2 and then mounted back
-	 * with ATTR1, keeping the di_forkoff's fixed but probably at
-	 * various positions. Therefore, for both ATTR1 and ATTR2
-	 * we have to assume the worst case scenario of a minimum size
-	 * available.
+	 * the fork offset of all the inodes will be
+	 * (xfs_default_attroffset(ip) >> 3) because we could have mounted
+	 * with ATTR2 and then mounted back with ATTR1, keeping the
+	 * di_forkoff's fixed but probably at various positions. Therefore,
+	 * for both ATTR1 and ATTR2 we have to assume the worst case scenario
+	 * of a minimum size available.
 	 */
 	if (whichfork == XFS_DATA_FORK) {
 		maxleafents = MAXEXTNUM;
Index: xfs/fs/xfs/xfs_bmap.h
===================================================================
--- xfs.orig/fs/xfs/xfs_bmap.h	2009-02-09 19:15:18.763069338 +0100
+++ xfs/fs/xfs/xfs_bmap.h	2009-02-09 19:15:35.583944247 +0100
@@ -338,6 +338,10 @@ xfs_check_nostate_extents(
 	xfs_extnum_t		idx,
 	xfs_extnum_t		num);
 
+uint
+xfs_default_attroffset(
+	struct xfs_inode	*ip);
+
 #ifdef __KERNEL__
 
 /*
Index: xfs/fs/xfs/xfs_mount.h
===================================================================
--- xfs.orig/fs/xfs/xfs_mount.h	2009-02-09 19:15:29.084069385 +0100
+++ xfs/fs/xfs/xfs_mount.h	2009-02-09 19:15:35.584944583 +0100
@@ -276,7 +276,6 @@ typedef struct xfs_mount {
 	int			m_fixedfsid[2];	/* unchanged for life of FS */
 	uint			m_dmevmask;	/* DMI events for this FS */
 	__uint64_t		m_flags;	/* global mount flags */
-	uint			m_attroffset;	/* inode attribute offset */
 	uint			m_dir_node_ents; /* #entries in a dir danode */
 	uint			m_attr_node_ents; /* #entries in attr danode */
 	int			m_ialloc_inos;	/* inodes in inode allocation */

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

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 04/13] xfs: take inode version into account in XFS_LITINO
  2009-02-10 20:22 [PATCH 00/13] Updated CRC patches Christoph Hellwig
                   ` (2 preceding siblings ...)
  2009-02-10 20:22 ` [PATCH 03/13] xfs: remove m_attroffset Christoph Hellwig
@ 2009-02-10 20:22 ` Christoph Hellwig
  2009-02-10 20:22 ` [PATCH 05/13] xfs: add CRC infrastructure Christoph Hellwig
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 22+ messages in thread
From: Christoph Hellwig @ 2009-02-10 20:22 UTC (permalink / raw)
  To: xfs

[-- Attachment #1: xfs-XFS_LITINO-per-inode --]
[-- Type: text/plain, Size: 4137 bytes --]

Add a version argument to XFS_LITINO so that it can return different values
depending on the inode version.  This is required for the upcoming v3 inodes
with a larger fixed layout dinode.


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

Index: xfs/fs/xfs/xfs_dinode.h
===================================================================
--- xfs.orig/fs/xfs/xfs_dinode.h	2009-02-09 19:15:29.082068921 +0100
+++ xfs/fs/xfs/xfs_dinode.h	2009-02-09 19:15:37.179944489 +0100
@@ -103,7 +103,7 @@ typedef enum xfs_dinode_fmt {
 /*
  * Inode size for given fs.
  */
-#define XFS_LITINO(mp) \
+#define XFS_LITINO(version, mp) \
 	((int)(((mp)->m_sb.sb_inodesize) - sizeof(struct xfs_dinode)))
 
 #define	XFS_BROOT_SIZE_ADJ	\
@@ -118,10 +118,10 @@ typedef enum xfs_dinode_fmt {
 #define XFS_DFORK_DSIZE(dip,mp) \
 	(XFS_DFORK_Q(dip) ? \
 		XFS_DFORK_BOFF(dip) : \
-		XFS_LITINO(mp))
+		XFS_LITINO((dip)->di_version, mp))
 #define XFS_DFORK_ASIZE(dip,mp) \
 	(XFS_DFORK_Q(dip) ? \
-		XFS_LITINO(mp) - XFS_DFORK_BOFF(dip) : \
+		XFS_LITINO((dip)->di_version, mp) - XFS_DFORK_BOFF(dip) : \
 		0)
 #define XFS_DFORK_SIZE(dip,mp,w) \
 	((w) == XFS_DATA_FORK ? \
Index: xfs/fs/xfs/xfs_attr_leaf.c
===================================================================
--- xfs.orig/fs/xfs/xfs_attr_leaf.c	2009-02-09 19:15:35.580944493 +0100
+++ xfs/fs/xfs/xfs_attr_leaf.c	2009-02-09 19:15:37.185944554 +0100
@@ -127,7 +127,8 @@ xfs_attr_shortform_bytesfit(xfs_inode_t 
 	int dsize;	
 	xfs_mount_t *mp = dp->i_mount;
 
-	offset = (XFS_LITINO(mp) - bytes) >> 3; /* rounded down */
+	/* rounded down */
+	offset = (XFS_LITINO(dp->i_d.di_version, mp) - bytes) >> 3;
 
 	switch (dp->i_d.di_format) {
 	case XFS_DINODE_FMT_DEV:
@@ -185,7 +186,8 @@ xfs_attr_shortform_bytesfit(xfs_inode_t 
 	minforkoff = roundup(minforkoff, 8) >> 3;
 
 	/* attr fork btree root can have at least this many key/ptr pairs */
-	maxforkoff = XFS_LITINO(mp) - XFS_BMDR_SPACE_CALC(MINABTPTRS);
+	maxforkoff = XFS_LITINO(dp->i_d.di_version, mp) -
+			XFS_BMDR_SPACE_CALC(MINABTPTRS);
 	maxforkoff = maxforkoff >> 3;	/* rounded down */
 
 	if (offset >= minforkoff && offset < maxforkoff)
Index: xfs/fs/xfs/xfs_bmap.c
===================================================================
--- xfs.orig/fs/xfs/xfs_bmap.c	2009-02-09 19:15:35.583944247 +0100
+++ xfs/fs/xfs/xfs_bmap.c	2009-02-09 19:15:37.192068867 +0100
@@ -3587,13 +3587,13 @@ xfs_default_attroffset(
 	uint			offset;
 
 	if (mp->m_sb.sb_inodesize == 256) {
-		offset = XFS_LITINO(mp) -
+		offset = XFS_LITINO(ip->i_d.di_version, mp) -
 				XFS_BMDR_SPACE_CALC(MINABTPTRS);
 	} else {
 		offset = XFS_BMDR_SPACE_CALC(6 * MINABTPTRS);
 	}
 
-	ASSERT(offset < XFS_LITINO(mp));
+	ASSERT(offset < XFS_LITINO(ip->i_d.di_version, mp));
 	return offset;
 }
 
Index: xfs/fs/xfs/xfs_inode.h
===================================================================
--- xfs.orig/fs/xfs/xfs_inode.h	2009-02-09 19:15:18.690944589 +0100
+++ xfs/fs/xfs/xfs_inode.h	2009-02-09 19:15:37.193072276 +0100
@@ -180,10 +180,11 @@ typedef struct xfs_icdinode {
 #define XFS_IFORK_DSIZE(ip) \
 	(XFS_IFORK_Q(ip) ? \
 		XFS_IFORK_BOFF(ip) : \
-		XFS_LITINO((ip)->i_mount))
+		XFS_LITINO((ip)->i_d.di_version, (ip)->i_mount))
 #define XFS_IFORK_ASIZE(ip) \
 	(XFS_IFORK_Q(ip) ? \
-		XFS_LITINO((ip)->i_mount) - XFS_IFORK_BOFF(ip) : \
+		XFS_LITINO((ip)->i_d.di_version, (ip)->i_mount) - \
+			XFS_IFORK_BOFF(ip) : \
 		0)
 #define XFS_IFORK_SIZE(ip,w) \
 	((w) == XFS_DATA_FORK ? \
Index: xfs/fs/xfs/xfs_vnodeops.c
===================================================================
--- xfs.orig/fs/xfs/xfs_vnodeops.c	2009-02-09 19:15:18.700944674 +0100
+++ xfs/fs/xfs/xfs_vnodeops.c	2009-02-09 19:15:37.194069750 +0100
@@ -2210,7 +2210,7 @@ xfs_symlink(
 	 * The symlink will fit into the inode data fork?
 	 * There can't be any attributes so we get the whole variable part.
 	 */
-	if (pathlen <= XFS_LITINO(mp))
+	if (pathlen <= XFS_LITINO(dp->i_d.di_version, mp))
 		fs_blocks = 0;
 	else
 		fs_blocks = XFS_B_TO_FSB(mp, pathlen);

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

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 05/13] xfs: add CRC infrastructure
  2009-02-10 20:22 [PATCH 00/13] Updated CRC patches Christoph Hellwig
                   ` (3 preceding siblings ...)
  2009-02-10 20:22 ` [PATCH 04/13] xfs: take inode version into account in XFS_LITINO Christoph Hellwig
@ 2009-02-10 20:22 ` 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
                   ` (7 subsequent siblings)
  12 siblings, 1 reply; 22+ messages in thread
From: Christoph Hellwig @ 2009-02-10 20:22 UTC (permalink / raw)
  To: xfs

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

 - add a mount feature bit for CRC enabled filesystems
 - add some helpers for generating and verifying the CRCs
 - add a copy_uuid helper
 - add a pre-io callback to xfs_buf for calculating the CRCs

The checksumming helpers are losely based on similar ones in sctp,
all other bits come from Dave Chinner.


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

Index: xfs/fs/xfs/Kconfig
===================================================================
--- xfs.orig/fs/xfs/Kconfig	2009-02-03 16:52:11.665916316 +0100
+++ xfs/fs/xfs/Kconfig	2009-02-05 19:04:41.218218577 +0100
@@ -2,6 +2,7 @@ config XFS_FS
 	tristate "XFS filesystem support"
 	depends on BLOCK
 	select EXPORTFS
+	select LIBCRC32C
 	help
 	  XFS is a high performance journaling filesystem which originated
 	  on the SGI IRIX platform.  It is completely multi-threaded, can
Index: xfs/fs/xfs/linux-2.6/xfs_linux.h
===================================================================
--- xfs.orig/fs/xfs/linux-2.6/xfs_linux.h	2009-02-05 17:53:06.742088475 +0100
+++ xfs/fs/xfs/linux-2.6/xfs_linux.h	2009-02-05 19:04:31.269945065 +0100
@@ -72,6 +72,7 @@
 #include <linux/random.h>
 #include <linux/ctype.h>
 #include <linux/writeback.h>
+#include <linux/crc32c.h>
 
 #include <asm/page.h>
 #include <asm/div64.h>
Index: xfs/fs/xfs/xfs_sb.h
===================================================================
--- xfs.orig/fs/xfs/xfs_sb.h	2009-02-03 16:52:12.358436358 +0100
+++ xfs/fs/xfs/xfs_sb.h	2009-02-05 19:04:31.272973243 +0100
@@ -80,10 +80,12 @@ struct xfs_mount;
 #define XFS_SB_VERSION2_RESERVED4BIT	0x00000004
 #define XFS_SB_VERSION2_ATTR2BIT	0x00000008	/* Inline attr rework */
 #define XFS_SB_VERSION2_PARENTBIT	0x00000010	/* parent pointers */
+#define XFS_SB_VERSION2_CRCBIT		0x00000020	/* metadata has CRCs */
 
 #define	XFS_SB_VERSION2_OKREALFBITS	\
 	(XFS_SB_VERSION2_LAZYSBCOUNTBIT	| \
-	 XFS_SB_VERSION2_ATTR2BIT)
+	 XFS_SB_VERSION2_ATTR2BIT | \
+	 XFS_SB_VERSION2_CRCBIT)
 #define	XFS_SB_VERSION2_OKSASHFBITS	\
 	(0)
 #define XFS_SB_VERSION2_OKREALBITS	\
@@ -495,6 +497,12 @@ static inline void xfs_sb_version_remove
 		sbp->sb_versionnum &= ~XFS_SB_VERSION_MOREBITSBIT;
 }
 
+static inline int xfs_sb_version_hascrc(xfs_sb_t *sbp)
+{
+	return (xfs_sb_version_hasmorebits(sbp) &&
+		(sbp->sb_features2 & XFS_SB_VERSION2_CRCBIT));
+}
+
 /*
  * end of superblock version macros
  */
Index: xfs/fs/xfs/linux-2.6/xfs_buf.c
===================================================================
--- xfs.orig/fs/xfs/linux-2.6/xfs_buf.c	2009-02-05 17:53:06.643944544 +0100
+++ xfs/fs/xfs/linux-2.6/xfs_buf.c	2009-02-05 19:04:31.273973789 +0100
@@ -1108,6 +1108,14 @@ _xfs_buf_ioapply(
 		     (bp->b_flags & XBF_READ_AHEAD) ? READA : READ;
 	}
 
+	/*
+	 * call out to buffer specific pre-write I/O functions. Used for
+	 * validation of buffers and CRC calculations prior to I/O issue.
+	 */
+	if (bp->b_io_callback && (bp->b_flags & XBF_WRITE))
+		bp->b_io_callback(bp);
+
+
 	/* Special code path for reading a sub page size buffer in --
 	 * we populate up the whole page, and hence the other metadata
 	 * in the same page.  This optimization is only valid when the
Index: xfs/fs/xfs/linux-2.6/xfs_buf.h
===================================================================
--- xfs.orig/fs/xfs/linux-2.6/xfs_buf.h	2009-01-21 21:03:27.825295146 +0100
+++ xfs/fs/xfs/linux-2.6/xfs_buf.h	2009-02-05 19:04:31.273973789 +0100
@@ -174,6 +174,8 @@ typedef struct xfs_buf {
 	unsigned int		b_offset;	/* page offset in first page */
 	struct page		**b_pages;	/* array of page pointers */
 	struct page		*b_page_array[XB_PAGES]; /* inline pages */
+	void			(*b_io_callback)(struct xfs_buf *);
+						/* pre-write I/O callback */
 #ifdef XFS_BUF_LOCK_TRACKING
 	int			b_last_holder;
 #endif
@@ -236,6 +238,16 @@ static inline int xfs_buf_geterror(xfs_b
 /* Buffer Utility Routines */
 extern xfs_caddr_t xfs_buf_offset(xfs_buf_t *, size_t);
 
+/*
+ * Set the function that should be called immediately prior
+ * to a write I/O being issued on this buffer.
+ */
+static inline void
+xfs_buf_set_io_callback(xfs_buf_t *bp, void (*func)(xfs_buf_t *))
+{
+	bp->b_io_callback = func;
+}
+
 /* Pinning Buffer Storage in Memory */
 extern void xfs_buf_pin(xfs_buf_t *);
 extern void xfs_buf_unpin(xfs_buf_t *);
Index: xfs/fs/xfs/support/uuid.c
===================================================================
--- xfs.orig/fs/xfs/support/uuid.c	2009-01-21 21:03:27.838294778 +0100
+++ xfs/fs/xfs/support/uuid.c	2009-02-05 19:04:31.274944514 +0100
@@ -72,6 +72,12 @@ uuid_equal(uuid_t *uuid1, uuid_t *uuid2)
 	return memcmp(uuid1, uuid2, sizeof(uuid_t)) ? 0 : 1;
 }
 
+void
+uuid_copy(uuid_t *dst, uuid_t *src)
+{
+	memcpy(dst, src, sizeof(uuid_t));
+}
+
 /*
  * Given a 128-bit uuid, return a 64-bit value by adding the top and bottom
  * 64-bit words.  NOTE: This function can not be changed EVER.  Although
Index: xfs/fs/xfs/support/uuid.h
===================================================================
--- xfs.orig/fs/xfs/support/uuid.h	2009-01-21 21:03:27.838294778 +0100
+++ xfs/fs/xfs/support/uuid.h	2009-02-05 19:04:31.279944870 +0100
@@ -25,6 +25,7 @@ typedef struct {
 extern void uuid_create_nil(uuid_t *uuid);
 extern int uuid_is_nil(uuid_t *uuid);
 extern int uuid_equal(uuid_t *uuid1, uuid_t *uuid2);
+extern void uuid_copy(uuid_t *dst, uuid_t *src);
 extern void uuid_getnodeuniq(uuid_t *uuid, int fsid [2]);
 extern __uint64_t uuid_hash64(uuid_t *uuid);
 extern int uuid_table_insert(uuid_t *uuid);
Index: xfs/fs/xfs/xfs_cksum.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ xfs/fs/xfs/xfs_cksum.h	2009-02-05 19:04:31.282972630 +0100
@@ -0,0 +1,62 @@
+#ifndef _XFS_CKSUM_H
+#define _XFS_CKSUM_H 1
+
+#define XFS_CRC_SEED	(~(__uint32_t)0)
+
+/*
+ * Calculate the intermediate checksum for a buffer that has the CRC field
+ * inside it.  The offset of the 32bit crc fields is passed as the
+ * cksum_offset parameter.
+ */
+static inline __uint32_t
+xfs_start_cksum(char *buffer, size_t length, unsigned long cksum_offset)
+{
+	__uint32_t zero = 0;
+	__uint32_t crc;
+
+	/* Calculate CRC up to the checksum. */
+	crc = crc32c(XFS_CRC_SEED, buffer, cksum_offset);
+
+	/* Skip checksum field */
+	crc = crc32c(crc, &zero, sizeof(__u32));
+
+	/* Calculate the rest of the CRC. */
+	return crc32c(crc, &buffer[cksum_offset + sizeof(__be32)],
+		      length - (cksum_offset + sizeof(__be32)));
+}
+
+/*
+ * Convert the intermediate checksum to the final ondisk format.
+ *
+ * Note that crc32c is already endianess agnostic, so no additional
+ * byte swap is needed.
+ */
+static inline __be32
+xfs_end_cksum(__uint32_t crc)
+{
+	return (__force __be32)~crc;
+}
+
+/*
+ * Helper to generate the checksum for a buffer.
+ */
+static inline void
+xfs_update_cksum(char *buffer, size_t length, unsigned long cksum_offset)
+{
+	__uint32_t crc = xfs_start_cksum(buffer, length, cksum_offset);
+
+	*(__be32 *)(buffer + cksum_offset) = xfs_end_cksum(crc);
+}
+
+/*
+ * Helper to verify the checksum for a buffer.
+ */
+static inline int
+xfs_verify_cksum(char *buffer, size_t length, unsigned long cksum_offset)
+{
+	__uint32_t crc = xfs_start_cksum(buffer, length, cksum_offset);
+
+	return *(__be32 *)(buffer + cksum_offset) == xfs_end_cksum(crc);
+}
+
+#endif /* _XFS_CKSUM_H */
Index: xfs/fs/xfs/xfs_mount.c
===================================================================
--- xfs.orig/fs/xfs/xfs_mount.c	2009-02-05 17:53:07.338944053 +0100
+++ xfs/fs/xfs/xfs_mount.c	2009-02-05 19:04:31.286943944 +0100
@@ -569,6 +569,11 @@ xfs_mount_common(xfs_mount_t *mp, xfs_sb
 	ASSERT(sbp->sb_inodesize ==  256 || sbp->sb_inodesize ==  512 ||
 	       sbp->sb_inodesize == 1024 || sbp->sb_inodesize == 2048);
 
+	if (xfs_sb_version_hascrc(sbp))
+		printk("XFS: using CRCs\n");
+	else
+		printk("XFS: not using CRCs\n");
+
 	mp->m_agfrotor = mp->m_agirotor = 0;
 	spin_lock_init(&mp->m_agirotor_lock);
 	mp->m_maxagi = mp->m_sb.sb_agcount;

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

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 06/13] xfs: add support for large btree blocks
  2009-02-10 20:22 [PATCH 00/13] Updated CRC patches Christoph Hellwig
                   ` (4 preceding siblings ...)
  2009-02-10 20:22 ` [PATCH 05/13] xfs: add CRC infrastructure Christoph Hellwig
@ 2009-02-10 20:22 ` Christoph Hellwig
  2009-02-10 20:22 ` [PATCH 07/13] xfs: add CRC checks to the superblock Christoph Hellwig
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 22+ messages in thread
From: Christoph Hellwig @ 2009-02-10 20:22 UTC (permalink / raw)
  To: xfs

[-- Attachment #1: xfs-large-btree-blocks --]
[-- Type: text/plain, Size: 36929 bytes --]

Add support for larger btree blocks that contains a CRC32C checksum, a
filesystem uuid and block number for detecting filesystem consistency
and out of place writes.


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

Index: xfs/fs/xfs/xfs_btree.h
===================================================================
--- xfs.orig/fs/xfs/xfs_btree.h	2009-02-09 19:05:49.005068530 +0100
+++ xfs/fs/xfs/xfs_btree.h	2009-02-09 19:15:42.836068971 +0100
@@ -47,6 +47,10 @@ extern kmem_zone_t	*xfs_btree_cur_zone;
  *
  * To get the size of the actual short or long form headers please use
  * the size macros below.  Never use sizeof(xfs_btree_block).
+ *
+ * The blkno, crc and uuid fields are only available in filesystems with
+ * the crc feature bit, and all accesses to them must be conditional on
+ * that flag.
  */
 struct xfs_btree_block {
 	__be32		bb_magic;	/* magic number for block type */
@@ -56,16 +60,32 @@ struct xfs_btree_block {
 		struct {
 			__be32		bb_leftsib;
 			__be32		bb_rightsib;
+
+			__be64		bb_blkno;
+			uuid_t		bb_uuid;
+			__be32		bb_crc;
+			__be32		bb_pad; /* padding for alignment */
 		} s;			/* short form pointers */
 		struct	{
 			__be64		bb_leftsib;
 			__be64		bb_rightsib;
+
+			__be64		bb_blkno;
+			uuid_t		bb_uuid;
+			__be32		bb_crc;
+			__be32		bb_pad; /* padding for alignment */
 		} l;			/* long form pointers */
 	} bb_u;				/* rest */
 };
 
 #define XFS_BTREE_SBLOCK_LEN	16	/* size of a short form block */
 #define XFS_BTREE_LBLOCK_LEN	24	/* size of a long form block */
+#define XFS_BTREE_CRCBLOCK_ADD	32	/* size of blkno + crc + uuid */
+
+#define XFS_BTREE_SBLOCK_CRC_OFF \
+	offsetof(struct xfs_btree_block, bb_u.s.bb_crc)
+#define XFS_BTREE_LBLOCK_CRC_OFF \
+	offsetof(struct xfs_btree_block, bb_u.l.bb_crc)
 
 
 /*
@@ -101,13 +121,11 @@ union xfs_btree_rec {
 #define	XFS_BB_NUMRECS		0x04
 #define	XFS_BB_LEFTSIB		0x08
 #define	XFS_BB_RIGHTSIB		0x10
+#define XFS_BB_BLKNO		0x20
 #define	XFS_BB_NUM_BITS		5
 #define	XFS_BB_ALL_BITS		((1 << XFS_BB_NUM_BITS) - 1)
-
-/*
- * Magic numbers for btree blocks.
- */
-extern const __uint32_t	xfs_magics[];
+#define	XFS_BB_NUM_BITS_CRC	8
+#define	XFS_BB_ALL_BITS_CRC	((1 << XFS_BB_NUM_BITS_CRC) - 1)
 
 /*
  * Generic stats interface
@@ -275,6 +293,7 @@ typedef struct xfs_btree_cur
 #define XFS_BTREE_LONG_PTRS		(1<<0)	/* pointers are 64bits long */
 #define XFS_BTREE_ROOT_IN_INODE		(1<<1)	/* root may be variable size */
 #define XFS_BTREE_LASTREC_UPDATE	(1<<2)	/* track last rec externally */
+#define XFS_BTREE_CRC_BLOCKS		(1<<3)	/* uses extended btree blocks */
 
 
 #define	XFS_BTREE_NOERROR	0
@@ -438,6 +457,12 @@ int xfs_btree_delete(struct xfs_btree_cu
 int xfs_btree_get_rec(struct xfs_btree_cur *, union xfs_btree_rec **, int *);
 
 /*
+ * CRC calculation is also needed for growfs.
+ */
+void xfs_btree_lblock_calc_crc(struct xfs_buf *);
+void xfs_btree_sblock_calc_crc(struct xfs_buf *);
+
+/*
  * Internal btree helpers also used by xfs_bmap.c.
  */
 void xfs_btree_log_block(struct xfs_btree_cur *, struct xfs_buf *, int);
Index: xfs/fs/xfs/xfs_bmap_btree.c
===================================================================
--- xfs.orig/fs/xfs/xfs_bmap_btree.c	2009-02-09 19:05:49.009069179 +0100
+++ xfs/fs/xfs/xfs_bmap_btree.c	2009-02-09 19:15:42.838069994 +0100
@@ -77,12 +77,20 @@ xfs_bmdr_to_bmbt(
 	xfs_bmbt_key_t		*tkp;
 	__be64			*tpp;
 
-	rblock->bb_magic = cpu_to_be32(XFS_BMAP_MAGIC);
+	if (xfs_sb_version_hascrc(&mp->m_sb))
+		rblock->bb_magic = cpu_to_be32(XFS_BMAP_MAGIC);
+	else
+		rblock->bb_magic = cpu_to_be32(XFS_BMAP_CRC_MAGIC);
 	rblock->bb_level = dblock->bb_level;
 	ASSERT(be16_to_cpu(rblock->bb_level) > 0);
 	rblock->bb_numrecs = dblock->bb_numrecs;
 	rblock->bb_u.l.bb_leftsib = cpu_to_be64(NULLDFSBNO);
 	rblock->bb_u.l.bb_rightsib = cpu_to_be64(NULLDFSBNO);
+	if (xfs_sb_version_hascrc(&mp->m_sb)) {
+		rblock->bb_u.l.bb_blkno = cpu_to_be64(XFS_BUF_DADDR_NULL);
+		uuid_copy(&rblock->bb_u.l.bb_uuid, &mp->m_sb.sb_uuid);
+		rblock->bb_u.l.bb_pad = 0;
+	}
 	dmxr = xfs_bmdr_maxrecs(mp, dblocklen, 0);
 	fkp = XFS_BMDR_KEY_ADDR(dblock, 1);
 	tkp = XFS_BMBT_KEY_ADDR(mp, rblock, 1);
@@ -441,10 +449,18 @@ xfs_bmbt_to_bmdr(
 	xfs_bmbt_key_t		*tkp;
 	__be64			*tpp;
 
-	ASSERT(be32_to_cpu(rblock->bb_magic) == XFS_BMAP_MAGIC);
+	if (xfs_sb_version_hascrc(&mp->m_sb))
+		ASSERT(be32_to_cpu(rblock->bb_magic) == XFS_BMAP_CRC_MAGIC);
+	else
+		ASSERT(be32_to_cpu(rblock->bb_magic) == XFS_BMAP_MAGIC);
 	ASSERT(be64_to_cpu(rblock->bb_u.l.bb_leftsib) == NULLDFSBNO);
 	ASSERT(be64_to_cpu(rblock->bb_u.l.bb_rightsib) == NULLDFSBNO);
 	ASSERT(be16_to_cpu(rblock->bb_level) > 0);
+	if (xfs_sb_version_hascrc(&mp->m_sb)) {
+		ASSERT(uuid_equal(&rblock->bb_u.l.bb_uuid, &mp->m_sb.sb_uuid));
+		ASSERT(rblock->bb_u.l.bb_blkno ==
+		       cpu_to_be64(XFS_BUF_DADDR_NULL));
+	}
 	dblock->bb_level = rblock->bb_level;
 	dblock->bb_numrecs = rblock->bb_numrecs;
 	dmxr = xfs_bmdr_maxrecs(mp, dblocklen, 0);
@@ -886,6 +902,8 @@ xfs_bmbt_init_cursor(
 
 	cur->bc_ops = &xfs_bmbt_ops;
 	cur->bc_flags = XFS_BTREE_LONG_PTRS | XFS_BTREE_ROOT_IN_INODE;
+	if (xfs_sb_version_hascrc(&mp->m_sb))
+		cur->bc_flags |= XFS_BTREE_CRC_BLOCKS;
 
 	cur->bc_private.b.forksize = XFS_IFORK_SIZE(ip, whichfork);
 	cur->bc_private.b.ip = ip;
Index: xfs/fs/xfs/xfs_bmap_btree.h
===================================================================
--- xfs.orig/fs/xfs/xfs_bmap_btree.h	2009-02-09 19:05:49.013068710 +0100
+++ xfs/fs/xfs/xfs_bmap_btree.h	2009-02-09 19:15:42.838069994 +0100
@@ -18,7 +18,8 @@
 #ifndef __XFS_BMAP_BTREE_H__
 #define __XFS_BMAP_BTREE_H__
 
-#define XFS_BMAP_MAGIC	0x424d4150	/* 'BMAP' */
+#define XFS_BMAP_MAGIC		0x424d4150	/* 'BMAP' */
+#define XFS_BMAP_CRC_MAGIC	0x424d4158
 
 struct xfs_btree_cur;
 struct xfs_btree_block;
@@ -144,10 +145,11 @@ typedef __be64 xfs_bmbt_ptr_t, xfs_bmdr_
 
 /*
  * Btree block header size depends on a superblock flag.
- *
- * (not quite yet, but soon)
  */
-#define XFS_BMBT_BLOCK_LEN(mp)	XFS_BTREE_LBLOCK_LEN
+#define XFS_BMBT_BLOCK_LEN(mp) \
+	(xfs_sb_version_hascrc(&((mp)->m_sb)) ? \
+	 XFS_BTREE_LBLOCK_LEN + XFS_BTREE_CRCBLOCK_ADD : \
+	 XFS_BTREE_LBLOCK_LEN)
 
 #define XFS_BMBT_REC_ADDR(mp, block, index) \
 	((xfs_bmbt_rec_t *) \
@@ -194,12 +196,12 @@ typedef __be64 xfs_bmbt_ptr_t, xfs_bmdr_
 #define XFS_BMAP_BROOT_PTR_ADDR(mp, bb, i, sz) \
 	XFS_BMBT_PTR_ADDR(mp, bb, i, xfs_bmbt_maxrecs(mp, sz, 0))
 
-#define XFS_BMAP_BROOT_SPACE_CALC(nrecs) \
-	(int)(XFS_BTREE_LBLOCK_LEN + \
+#define XFS_BMAP_BROOT_SPACE_CALC(mp, nrecs) \
+	(int)(XFS_BMBT_BLOCK_LEN(mp) + \
 	       ((nrecs) * (sizeof(xfs_bmbt_key_t) + sizeof(xfs_bmbt_ptr_t))))
 
-#define XFS_BMAP_BROOT_SPACE(bb) \
-	(XFS_BMAP_BROOT_SPACE_CALC(be16_to_cpu((bb)->bb_numrecs)))
+#define XFS_BMAP_BROOT_SPACE(mp, bb) \
+	(XFS_BMAP_BROOT_SPACE_CALC(mp, be16_to_cpu((bb)->bb_numrecs)))
 #define XFS_BMDR_SPACE_CALC(nrecs) \
 	(int)(sizeof(xfs_bmdr_block_t) + \
 	       ((nrecs) * (sizeof(xfs_bmbt_key_t) + sizeof(xfs_bmbt_ptr_t))))
Index: xfs/fs/xfs/xfs_btree.c
===================================================================
--- xfs.orig/fs/xfs/xfs_btree.c	2009-02-09 19:05:49.018069067 +0100
+++ xfs/fs/xfs/xfs_btree.c	2009-02-09 19:15:42.842069176 +0100
@@ -39,6 +39,7 @@
 #include "xfs_btree_trace.h"
 #include "xfs_ialloc.h"
 #include "xfs_error.h"
+#include "xfs_cksum.h"
 
 /*
  * Cursor allocation zone.
@@ -48,9 +49,13 @@ kmem_zone_t	*xfs_btree_cur_zone;
 /*
  * Btree magic numbers.
  */
-const __uint32_t xfs_magics[XFS_BTNUM_MAX] = {
-	XFS_ABTB_MAGIC, XFS_ABTC_MAGIC, XFS_BMAP_MAGIC, XFS_IBT_MAGIC
+static const __uint32_t xfs_magics[2][XFS_BTNUM_MAX] = {
+	{ XFS_ABTB_MAGIC, XFS_ABTC_MAGIC, XFS_BMAP_MAGIC, XFS_IBT_MAGIC },
+	{ XFS_ABTB_CRC_MAGIC, XFS_ABTC_CRC_MAGIC,
+	  XFS_BMAP_CRC_MAGIC, XFS_IBT_CRC_MAGIC }
 };
+#define xfs_btree_magic(cur) \
+	xfs_magics[!!((cur)->bc_flags & XFS_BTREE_CRC_BLOCKS)][cur->bc_btnum]
 
 
 STATIC int				/* error (0 or EFSCORRUPTED) */
@@ -64,8 +69,34 @@ xfs_btree_check_lblock(
 	struct xfs_mount	*mp;	/* file system mount point */
 
 	mp = cur->bc_mp;
+
+	if (xfs_sb_version_hascrc(&mp->m_sb)) {
+		/*
+		 * Validate the CRC of the btree block only if the block is
+		 * clean (i.e. it just came from disk) and we have CRCs enabled.
+		 *
+		 * If we are called for an in inode root block don't check the
+		 * crc because we only calculate it for real btree blocks on
+		 * disk.
+		 */
+		if (bp && !(XFS_BUF_ISWRITE(bp) || XFS_BUF_ISDELAYWRITE(bp)) &&
+		    !xfs_verify_cksum(XFS_BUF_PTR(bp), XFS_BUF_SIZE(bp),
+		    		      XFS_BTREE_LBLOCK_CRC_OFF)) {
+			XFS_CORRUPTION_ERROR("xfs_btree_check_lblock crc",
+				XFS_ERRLEVEL_LOW, mp, mp);
+			return XFS_ERROR(EFSCORRUPTED);
+		}
+
+		lblock_ok =
+			uuid_equal(&block->bb_u.l.bb_uuid, &mp->m_sb.sb_uuid) &&
+			block->bb_u.l.bb_blkno == cpu_to_be64(
+				bp ? XFS_BUF_ADDR(bp) : XFS_BUF_DADDR_NULL);
+		if (!lblock_ok)
+			goto test_error;
+	}
+
 	lblock_ok =
-		be32_to_cpu(block->bb_magic) == xfs_magics[cur->bc_btnum] &&
+		be32_to_cpu(block->bb_magic) == xfs_btree_magic(cur) &&
 		be16_to_cpu(block->bb_level) == level &&
 		be16_to_cpu(block->bb_numrecs) <=
 			cur->bc_ops->get_maxrecs(cur, level) &&
@@ -77,6 +108,8 @@ xfs_btree_check_lblock(
 		(be64_to_cpu(block->bb_u.l.bb_rightsib) == NULLDFSBNO ||
 		 XFS_FSB_SANITY_CHECK(mp,
 		 	be64_to_cpu(block->bb_u.l.bb_rightsib)));
+
+ test_error:
 	if (unlikely(XFS_TEST_ERROR(!lblock_ok, mp,
 			XFS_ERRTAG_BTREE_CHECK_LBLOCK,
 			XFS_RANDOM_BTREE_CHECK_LBLOCK))) {
@@ -96,16 +129,40 @@ xfs_btree_check_sblock(
 	int			level,	/* level of the btree block */
 	struct xfs_buf		*bp)	/* buffer containing block */
 {
+	struct xfs_mount	*mp;	/* file system mount point */
 	struct xfs_buf		*agbp;	/* buffer for ag. freespace struct */
 	struct xfs_agf		*agf;	/* ag. freespace structure */
 	xfs_agblock_t		agflen;	/* native ag. freespace length */
 	int			sblock_ok; /* block passes checks */
 
+	mp = cur->bc_mp;
 	agbp = cur->bc_private.a.agbp;
 	agf = XFS_BUF_TO_AGF(agbp);
 	agflen = be32_to_cpu(agf->agf_length);
+
+	if (xfs_sb_version_hascrc(&mp->m_sb)) {
+		/*
+		 * Validate the CRC of the btree block only if the block is
+		 * clean (i.e. it just came from disk) and we have CRCs enabled.
+		 */
+		if (!(XFS_BUF_ISWRITE(bp) || XFS_BUF_ISDELAYWRITE(bp)) &&
+		    !xfs_verify_cksum(XFS_BUF_PTR(bp), XFS_BUF_SIZE(bp),
+			    	      XFS_BTREE_SBLOCK_CRC_OFF)) {
+			XFS_CORRUPTION_ERROR("xfs_btree_check_sblock crc",
+				XFS_ERRLEVEL_LOW, mp, mp);
+			return XFS_ERROR(EFSCORRUPTED);
+		}
+
+		sblock_ok =
+			uuid_equal(&block->bb_u.s.bb_uuid, &mp->m_sb.sb_uuid) &&
+			block->bb_u.s.bb_blkno == cpu_to_be64(
+				bp ? XFS_BUF_ADDR(bp) : XFS_BUF_DADDR_NULL);
+		if (!sblock_ok)
+			goto test_error;
+	}
+
 	sblock_ok =
-		be32_to_cpu(block->bb_magic) == xfs_magics[cur->bc_btnum] &&
+		be32_to_cpu(block->bb_magic) == xfs_btree_magic(cur) &&
 		be16_to_cpu(block->bb_level) == level &&
 		be16_to_cpu(block->bb_numrecs) <=
 			cur->bc_ops->get_maxrecs(cur, level) &&
@@ -115,13 +172,15 @@ xfs_btree_check_sblock(
 		(be32_to_cpu(block->bb_u.s.bb_rightsib) == NULLAGBLOCK ||
 		 be32_to_cpu(block->bb_u.s.bb_rightsib) < agflen) &&
 		block->bb_u.s.bb_rightsib;
-	if (unlikely(XFS_TEST_ERROR(!sblock_ok, cur->bc_mp,
+
+ test_error:
+	if (unlikely(XFS_TEST_ERROR(!sblock_ok, mp,
 			XFS_ERRTAG_BTREE_CHECK_SBLOCK,
 			XFS_RANDOM_BTREE_CHECK_SBLOCK))) {
 		if (bp)
 			xfs_buftrace("SBTREE ERROR", bp);
 		XFS_ERROR_REPORT("xfs_btree_check_sblock", XFS_ERRLEVEL_LOW,
-				 cur->bc_mp);
+				 mp);
 		return XFS_ERROR(EFSCORRUPTED);
 	}
 	return 0;
@@ -272,18 +331,28 @@ xfs_btree_dup_cursor(
 	for (i = 0; i < new->bc_nlevels; i++) {
 		new->bc_ptrs[i] = cur->bc_ptrs[i];
 		new->bc_ra[i] = cur->bc_ra[i];
-		if ((bp = cur->bc_bufs[i])) {
-			if ((error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
-				XFS_BUF_ADDR(bp), mp->m_bsize, 0, &bp))) {
+		bp = cur->bc_bufs[i];
+		if (bp) {
+			error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
+				XFS_BUF_ADDR(bp), mp->m_bsize, 0, &bp);
+			if (error) {
 				xfs_btree_del_cursor(new, error);
 				*ncur = NULL;
 				return error;
 			}
-			new->bc_bufs[i] = bp;
+
 			ASSERT(bp);
 			ASSERT(!XFS_BUF_GETERROR(bp));
-		} else
-			new->bc_bufs[i] = NULL;
+
+			if (cur->bc_flags & XFS_BTREE_CRC_BLOCKS) {
+				xfs_buf_set_io_callback(bp,
+					(cur->bc_flags & XFS_BTREE_LONG_PTRS) ?
+						xfs_btree_lblock_calc_crc :
+						xfs_btree_sblock_calc_crc);
+			}
+
+		}
+		new->bc_bufs[i] = bp;
 	}
 	*ncur = new;
 	return 0;
@@ -324,9 +393,17 @@ xfs_btree_dup_cursor(
  */
 static inline size_t xfs_btree_block_len(struct xfs_btree_cur *cur)
 {
-	return (cur->bc_flags & XFS_BTREE_LONG_PTRS) ?
-		XFS_BTREE_LBLOCK_LEN :
-		XFS_BTREE_SBLOCK_LEN;
+	size_t len;
+
+	if (cur->bc_flags & XFS_BTREE_LONG_PTRS)
+		len = XFS_BTREE_LBLOCK_LEN;
+	else
+		len = XFS_BTREE_SBLOCK_LEN;
+
+	if (cur->bc_flags & XFS_BTREE_CRC_BLOCKS)
+		len += XFS_BTREE_CRCBLOCK_ADD;
+
+	return len;
 }
 
 /*
@@ -420,6 +497,30 @@ xfs_btree_ptr_addr(
 }
 
 /*
+ * Calculate CRC on the whole btree block and stuff it into the
+ * long-form btree header.
+ */
+void
+xfs_btree_lblock_calc_crc(
+	struct xfs_buf		*bp)
+{
+	xfs_update_cksum(XFS_BUF_PTR(bp), XFS_BUF_SIZE(bp),
+			 XFS_BTREE_LBLOCK_CRC_OFF);
+}
+
+/*
+ * Calculate CRC on the whole btree block and stuff it into the
+ * short-form btree header.
+ */
+void
+xfs_btree_sblock_calc_crc(
+	struct xfs_buf		*bp)
+{
+	xfs_update_cksum(XFS_BUF_PTR(bp), XFS_BUF_SIZE(bp),
+			 XFS_BTREE_SBLOCK_CRC_OFF);
+}
+
+/*
  * Get a the root block which is stored in the inode.
  *
  * For now this btree implementation assumes the btree root is always
@@ -474,6 +575,9 @@ xfs_btree_get_bufl(
 	bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, d, mp->m_bsize, lock);
 	ASSERT(bp);
 	ASSERT(!XFS_BUF_GETERROR(bp));
+
+	if (xfs_sb_version_hascrc(&mp->m_sb))
+		xfs_buf_set_io_callback(bp, xfs_btree_lblock_calc_crc);
 	return bp;
 }
 
@@ -498,6 +602,9 @@ xfs_btree_get_bufs(
 	bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, d, mp->m_bsize, lock);
 	ASSERT(bp);
 	ASSERT(!XFS_BUF_GETERROR(bp));
+
+	if (xfs_sb_version_hascrc(&mp->m_sb))
+		xfs_buf_set_io_callback(bp, xfs_btree_sblock_calc_crc);
 	return bp;
 }
 
@@ -640,6 +747,8 @@ xfs_btree_read_bufl(
 	ASSERT(!bp || !XFS_BUF_GETERROR(bp));
 	if (bp != NULL) {
 		XFS_BUF_SET_VTYPE_REF(bp, B_FS_MAP, refval);
+		if (xfs_sb_version_hascrc(&mp->m_sb))
+			xfs_buf_set_io_callback(bp, xfs_btree_lblock_calc_crc);
 	}
 	*bpp = bp;
 	return 0;
@@ -680,6 +789,8 @@ xfs_btree_read_bufs(
 			XFS_BUF_SET_VTYPE_REF(bp, B_FS_INOMAP, refval);
 			break;
 		}
+		if (xfs_sb_version_hascrc(&mp->m_sb))
+			xfs_buf_set_io_callback(bp, xfs_btree_sblock_calc_crc);
 	}
 	*bpp = bp;
 	return 0;
@@ -909,20 +1020,34 @@ xfs_btree_set_sibling(
 STATIC void
 xfs_btree_init_block(
 	struct xfs_btree_cur	*cur,
+	struct xfs_buf		*bp,
 	int			level,
-	int			numrecs,
-	struct xfs_btree_block	*new)	/* new block */
+	int			numrecs)
 {
-	new->bb_magic = cpu_to_be32(xfs_magics[cur->bc_btnum]);
+	struct xfs_btree_block	*new = XFS_BUF_TO_BLOCK(bp);
+
+	new->bb_magic = cpu_to_be32(xfs_btree_magic(cur));
 	new->bb_level = cpu_to_be16(level);
 	new->bb_numrecs = cpu_to_be16(numrecs);
 
 	if (cur->bc_flags & XFS_BTREE_LONG_PTRS) {
 		new->bb_u.l.bb_leftsib = cpu_to_be64(NULLDFSBNO);
 		new->bb_u.l.bb_rightsib = cpu_to_be64(NULLDFSBNO);
+		if (cur->bc_flags & XFS_BTREE_CRC_BLOCKS) {
+			new->bb_u.l.bb_blkno = cpu_to_be64(XFS_BUF_ADDR(bp));
+			uuid_copy(&new->bb_u.l.bb_uuid,
+				  &cur->bc_mp->m_sb.sb_uuid);
+			new->bb_u.l.bb_pad = 0;
+		}
 	} else {
 		new->bb_u.s.bb_leftsib = cpu_to_be32(NULLAGBLOCK);
 		new->bb_u.s.bb_rightsib = cpu_to_be32(NULLAGBLOCK);
+		if (cur->bc_flags & XFS_BTREE_CRC_BLOCKS) {
+			new->bb_u.s.bb_blkno = cpu_to_be64(XFS_BUF_ADDR(bp));
+			uuid_copy(&new->bb_u.s.bb_uuid,
+				  &cur->bc_mp->m_sb.sb_uuid);
+			new->bb_u.s.bb_pad = 0;
+		}
 	}
 }
 
@@ -1013,19 +1138,28 @@ xfs_btree_get_buf_block(
 	struct xfs_buf		**bpp)
 {
 	struct xfs_mount	*mp = cur->bc_mp;
+	struct xfs_buf		*bp;
 	xfs_daddr_t		d;
 
 	/* need to sort out how callers deal with failures first */
 	ASSERT(!(flags & XFS_BUF_TRYLOCK));
 
 	d = xfs_btree_ptr_to_daddr(cur, ptr);
-	*bpp = xfs_trans_get_buf(cur->bc_tp, mp->m_ddev_targp, d,
-				 mp->m_bsize, flags);
+	bp = xfs_trans_get_buf(cur->bc_tp, mp->m_ddev_targp, d,
+			       mp->m_bsize, flags);
 
-	ASSERT(*bpp);
-	ASSERT(!XFS_BUF_GETERROR(*bpp));
+	ASSERT(bp);
+	ASSERT(!XFS_BUF_GETERROR(bp));
+
+	if (cur->bc_flags & XFS_BTREE_CRC_BLOCKS) {
+		if (cur->bc_flags & XFS_BTREE_LONG_PTRS)
+			xfs_buf_set_io_callback(bp, xfs_btree_lblock_calc_crc);
+		else
+			xfs_buf_set_io_callback(bp, xfs_btree_sblock_calc_crc);
+	}
 
-	*block = XFS_BUF_TO_BLOCK(*bpp);
+	*block = XFS_BUF_TO_BLOCK(bp);
+	*bpp = bp;
 	return 0;
 }
 
@@ -1043,6 +1177,7 @@ xfs_btree_read_buf_block(
 	struct xfs_buf		**bpp)
 {
 	struct xfs_mount	*mp = cur->bc_mp;
+	struct xfs_buf		*bp;
 	xfs_daddr_t		d;
 	int			error;
 
@@ -1051,20 +1186,31 @@ xfs_btree_read_buf_block(
 
 	d = xfs_btree_ptr_to_daddr(cur, ptr);
 	error = xfs_trans_read_buf(mp, cur->bc_tp, mp->m_ddev_targp, d,
-				   mp->m_bsize, flags, bpp);
+				   mp->m_bsize, flags, &bp);
 	if (error)
 		return error;
 
-	ASSERT(*bpp != NULL);
-	ASSERT(!XFS_BUF_GETERROR(*bpp));
+	ASSERT(bp != NULL);
+	ASSERT(!XFS_BUF_GETERROR(bp));
 
-	xfs_btree_set_refs(cur, *bpp);
-	*block = XFS_BUF_TO_BLOCK(*bpp);
+	xfs_btree_set_refs(cur, bp);
+	*block = XFS_BUF_TO_BLOCK(bp);
 
-	error = xfs_btree_check_block(cur, *block, level, *bpp);
-	if (error)
-		xfs_trans_brelse(cur->bc_tp, *bpp);
-	return error;
+	if (cur->bc_flags & XFS_BTREE_CRC_BLOCKS) {
+		if (cur->bc_flags & XFS_BTREE_LONG_PTRS)
+			xfs_buf_set_io_callback(bp, xfs_btree_lblock_calc_crc);
+		else
+			xfs_buf_set_io_callback(bp, xfs_btree_sblock_calc_crc);
+	}
+
+	error = xfs_btree_check_block(cur, *block, level, bp);
+	if (error) {
+		xfs_trans_brelse(cur->bc_tp, bp);
+		return error;
+	}
+
+	*bpp = bp;
+	return 0;
 }
 
 /*
@@ -1250,31 +1396,56 @@ xfs_btree_log_block(
 {
 	int			first;	/* first byte offset logged */
 	int			last;	/* last byte offset logged */
-	static const short	soffsets[] = {	/* table of offsets (short) */
+	static const short	soffsets[] = {	/* short + crc */
 		offsetof(struct xfs_btree_block, bb_magic),
 		offsetof(struct xfs_btree_block, bb_level),
 		offsetof(struct xfs_btree_block, bb_numrecs),
 		offsetof(struct xfs_btree_block, bb_u.s.bb_leftsib),
 		offsetof(struct xfs_btree_block, bb_u.s.bb_rightsib),
-		XFS_BTREE_SBLOCK_LEN
+		offsetof(struct xfs_btree_block, bb_u.s.bb_blkno),
+		offsetof(struct xfs_btree_block, bb_u.s.bb_crc),
+		offsetof(struct xfs_btree_block, bb_u.s.bb_uuid),
+		offsetof(struct xfs_btree_block, bb_u.s.bb_pad),
+		XFS_BTREE_SBLOCK_LEN + XFS_BTREE_CRCBLOCK_ADD
 	};
-	static const short	loffsets[] = {	/* table of offsets (long) */
+	static const short	loffsets[] = {	/* long + crc */
 		offsetof(struct xfs_btree_block, bb_magic),
 		offsetof(struct xfs_btree_block, bb_level),
 		offsetof(struct xfs_btree_block, bb_numrecs),
 		offsetof(struct xfs_btree_block, bb_u.l.bb_leftsib),
 		offsetof(struct xfs_btree_block, bb_u.l.bb_rightsib),
-		XFS_BTREE_LBLOCK_LEN
+		offsetof(struct xfs_btree_block, bb_u.l.bb_blkno),
+		offsetof(struct xfs_btree_block, bb_u.l.bb_crc),
+		offsetof(struct xfs_btree_block, bb_u.l.bb_uuid),
+		offsetof(struct xfs_btree_block, bb_u.l.bb_pad),
+		XFS_BTREE_LBLOCK_LEN + XFS_BTREE_CRCBLOCK_ADD
 	};
 
 	XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY);
 	XFS_BTREE_TRACE_ARGBI(cur, bp, fields);
 
 	if (bp) {
+		int nbits;
+
+		if (cur->bc_flags & XFS_BTREE_CRC_BLOCKS) {
+			/*
+			 * We don't log the CRC when updating a btree
+			 * block but instead recreate it during log
+			 * recovery.  As the log buffers have checksums
+			 * of their this is safe and avoids logging a crc
+			 * update in a lot of places.
+			 */
+			if (fields == XFS_BB_ALL_BITS)
+				fields = XFS_BB_ALL_BITS_CRC;
+			nbits = XFS_BB_NUM_BITS_CRC;
+		} else {
+			nbits = XFS_BB_NUM_BITS;
+		}
+
 		xfs_btree_offsets(fields,
 				  (cur->bc_flags & XFS_BTREE_LONG_PTRS) ?
-					loffsets : soffsets,
-				  XFS_BB_NUM_BITS, &first, &last);
+				  	loffsets : soffsets,
+				  nbits, &first, &last);
 		xfs_trans_log_buf(cur->bc_tp, bp, first, last);
 	} else {
 		xfs_trans_log_inode(cur->bc_tp, cur->bc_private.b.ip,
@@ -2237,7 +2408,7 @@ xfs_btree_split(
 		goto error0;
 
 	/* Fill in the btree header for the new right block. */
-	xfs_btree_init_block(cur, xfs_btree_get_level(left), 0, right);
+	xfs_btree_init_block(cur, rbp, xfs_btree_get_level(left), 0);
 
 	/*
 	 * Split the entries between the old and the new block evenly.
@@ -2546,7 +2717,7 @@ xfs_btree_new_root(
 		nptr = 2;
 	}
 	/* Fill in the new block's btree header and log it. */
-	xfs_btree_init_block(cur, cur->bc_nlevels, 2, new);
+	xfs_btree_init_block(cur, nbp, cur->bc_nlevels, 2);
 	xfs_btree_log_block(cur, nbp, XFS_BB_ALL_BITS);
 	ASSERT(!xfs_btree_ptr_is_null(cur, &lptr) &&
 			!xfs_btree_ptr_is_null(cur, &rptr));
Index: xfs/fs/xfs/xfs_dinode.h
===================================================================
--- xfs.orig/fs/xfs/xfs_dinode.h	2009-02-09 19:15:37.179944489 +0100
+++ xfs/fs/xfs/xfs_dinode.h	2009-02-09 19:15:42.843068745 +0100
@@ -106,8 +106,8 @@ typedef enum xfs_dinode_fmt {
 #define XFS_LITINO(version, mp) \
 	((int)(((mp)->m_sb.sb_inodesize) - sizeof(struct xfs_dinode)))
 
-#define	XFS_BROOT_SIZE_ADJ	\
-	(XFS_BTREE_LBLOCK_LEN - sizeof(xfs_bmdr_block_t))
+#define XFS_BROOT_SIZE_ADJ(ip) \
+	(XFS_BMBT_BLOCK_LEN((ip)->i_mount) - sizeof(xfs_bmdr_block_t))
 
 /*
  * Inode data & attribute fork sizes, per inode.
Index: xfs/fs/xfs/xfs_inode.c
===================================================================
--- xfs.orig/fs/xfs/xfs_inode.c	2009-02-09 19:05:49.026068758 +0100
+++ xfs/fs/xfs/xfs_inode.c	2009-02-09 19:15:42.848068962 +0100
@@ -596,6 +596,7 @@ xfs_iformat_btree(
 	xfs_dinode_t		*dip,
 	int			whichfork)
 {
+	struct xfs_mount	*mp = ip->i_mount;
 	xfs_bmdr_block_t	*dfp;
 	xfs_ifork_t		*ifp;
 	/* REFERENCED */
@@ -604,7 +605,7 @@ xfs_iformat_btree(
 
 	ifp = XFS_IFORK_PTR(ip, whichfork);
 	dfp = (xfs_bmdr_block_t *)XFS_DFORK_PTR(dip, whichfork);
-	size = XFS_BMAP_BROOT_SPACE(dfp);
+	size = XFS_BMAP_BROOT_SPACE(mp, dfp);
 	nrecs = be16_to_cpu(dfp->bb_numrecs);
 
 	/*
@@ -616,13 +617,12 @@ xfs_iformat_btree(
 	 */
 	if (unlikely(XFS_IFORK_NEXTENTS(ip, whichfork) <= ifp->if_ext_max
 	    || XFS_BMDR_SPACE_CALC(nrecs) >
-			XFS_DFORK_SIZE(dip, ip->i_mount, whichfork)
+			XFS_DFORK_SIZE(dip, mp, whichfork)
 	    || XFS_IFORK_NEXTENTS(ip, whichfork) > ip->i_d.di_nblocks)) {
-		xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount,
+		xfs_fs_repair_cmn_err(CE_WARN, mp,
 			"corrupt inode %Lu (btree).",
 			(unsigned long long) ip->i_ino);
-		XFS_ERROR_REPORT("xfs_iformat_btree", XFS_ERRLEVEL_LOW,
-				 ip->i_mount);
+		XFS_ERROR_REPORT("xfs_iformat_btree", XFS_ERRLEVEL_LOW, mp);
 		return XFS_ERROR(EFSCORRUPTED);
 	}
 
@@ -2247,7 +2247,7 @@ xfs_iroot_realloc(
 		 * allocate it now and get out.
 		 */
 		if (ifp->if_broot_bytes == 0) {
-			new_size = (size_t)XFS_BMAP_BROOT_SPACE_CALC(rec_diff);
+			new_size = XFS_BMAP_BROOT_SPACE_CALC(mp, rec_diff);
 			ifp->if_broot = kmem_alloc(new_size, KM_SLEEP);
 			ifp->if_broot_bytes = (int)new_size;
 			return;
@@ -2261,9 +2261,9 @@ xfs_iroot_realloc(
 		 */
 		cur_max = xfs_bmbt_maxrecs(mp, ifp->if_broot_bytes, 0);
 		new_max = cur_max + rec_diff;
-		new_size = (size_t)XFS_BMAP_BROOT_SPACE_CALC(new_max);
+		new_size = (size_t)XFS_BMAP_BROOT_SPACE_CALC(mp, new_max);
 		ifp->if_broot = kmem_realloc(ifp->if_broot, new_size,
-				(size_t)XFS_BMAP_BROOT_SPACE_CALC(cur_max), /* old size */
+				(size_t)XFS_BMAP_BROOT_SPACE_CALC(mp, cur_max), /* old size */
 				KM_SLEEP);
 		op = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, ifp->if_broot, 1,
 						     ifp->if_broot_bytes);
@@ -2271,7 +2271,7 @@ xfs_iroot_realloc(
 						     (int)new_size);
 		ifp->if_broot_bytes = (int)new_size;
 		ASSERT(ifp->if_broot_bytes <=
-			XFS_IFORK_SIZE(ip, whichfork) + XFS_BROOT_SIZE_ADJ);
+			XFS_IFORK_SIZE(ip, whichfork) + XFS_BROOT_SIZE_ADJ(ip));
 		memmove(np, op, cur_max * (uint)sizeof(xfs_dfsbno_t));
 		return;
 	}
@@ -2286,7 +2286,7 @@ xfs_iroot_realloc(
 	new_max = cur_max + rec_diff;
 	ASSERT(new_max >= 0);
 	if (new_max > 0)
-		new_size = (size_t)XFS_BMAP_BROOT_SPACE_CALC(new_max);
+		new_size = (size_t)XFS_BMAP_BROOT_SPACE_CALC(mp, new_max);
 	else
 		new_size = 0;
 	if (new_size > 0) {
@@ -2294,7 +2294,8 @@ xfs_iroot_realloc(
 		/*
 		 * First copy over the btree block header.
 		 */
-		memcpy(new_broot, ifp->if_broot, XFS_BTREE_LBLOCK_LEN);
+		memcpy(new_broot, ifp->if_broot,
+			XFS_BMBT_BLOCK_LEN(ip->i_mount));
 	} else {
 		new_broot = NULL;
 		ifp->if_flags &= ~XFS_IFBROOT;
@@ -2324,7 +2325,7 @@ xfs_iroot_realloc(
 	ifp->if_broot = new_broot;
 	ifp->if_broot_bytes = (int)new_size;
 	ASSERT(ifp->if_broot_bytes <=
-		XFS_IFORK_SIZE(ip, whichfork) + XFS_BROOT_SIZE_ADJ);
+		XFS_IFORK_SIZE(ip, whichfork) + XFS_BROOT_SIZE_ADJ(ip));
 	return;
 }
 
@@ -2665,7 +2666,7 @@ xfs_iflush_fork(
 			ASSERT(ifp->if_broot != NULL);
 			ASSERT(ifp->if_broot_bytes <=
 			       (XFS_IFORK_SIZE(ip, whichfork) +
-				XFS_BROOT_SIZE_ADJ));
+				XFS_BROOT_SIZE_ADJ(ip)));
 			xfs_bmbt_to_bmdr(mp, ifp->if_broot, ifp->if_broot_bytes,
 				(xfs_bmdr_block_t *)cp,
 				XFS_DFORK_SIZE(dip, mp, whichfork));
Index: xfs/fs/xfs/xfs_attr_leaf.c
===================================================================
--- xfs.orig/fs/xfs/xfs_attr_leaf.c	2009-02-09 19:15:37.185944554 +0100
+++ xfs/fs/xfs/xfs_attr_leaf.c	2009-02-09 19:15:42.850068937 +0100
@@ -174,7 +174,7 @@ xfs_attr_shortform_bytesfit(xfs_inode_t 
 			else 
 				return dp->i_d.di_forkoff;
 		} else
-			dsize = XFS_BMAP_BROOT_SPACE(dp->i_df.if_broot);
+			dsize = XFS_BMAP_BROOT_SPACE(mp, dp->i_df.if_broot);
 		break;
 	}
 	
Index: xfs/fs/xfs/xfs_bmap.c
===================================================================
--- xfs.orig/fs/xfs/xfs_bmap.c	2009-02-09 19:15:37.192068867 +0100
+++ xfs/fs/xfs/xfs_bmap.c	2009-02-09 19:15:42.854098570 +0100
@@ -3465,6 +3465,7 @@ xfs_bmap_extents_to_btree(
 	xfs_extnum_t		nextents;	/* number of file extents */
 	xfs_bmbt_ptr_t		*pp;		/* root block address pointer */
 
+	mp = ip->i_mount;
 	ifp = XFS_IFORK_PTR(ip, whichfork);
 	ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS);
 	ASSERT(ifp->if_ext_max ==
@@ -3479,16 +3480,23 @@ xfs_bmap_extents_to_btree(
 	 * Fill in the root.
 	 */
 	block = ifp->if_broot;
-	block->bb_magic = cpu_to_be32(XFS_BMAP_MAGIC);
+	if (xfs_sb_version_hascrc(&mp->m_sb))
+		block->bb_magic = cpu_to_be32(XFS_BMAP_CRC_MAGIC);
+	else
+		block->bb_magic = cpu_to_be32(XFS_BMAP_MAGIC);
 	block->bb_level = cpu_to_be16(1);
 	block->bb_numrecs = cpu_to_be16(1);
 	block->bb_u.l.bb_leftsib = cpu_to_be64(NULLDFSBNO);
 	block->bb_u.l.bb_rightsib = cpu_to_be64(NULLDFSBNO);
+	if (xfs_sb_version_hascrc(&mp->m_sb)) {
+		block->bb_u.l.bb_blkno = cpu_to_be64(XFS_BUF_DADDR_NULL);
+		uuid_copy(&block->bb_u.l.bb_uuid, &mp->m_sb.sb_uuid);
+		block->bb_u.l.bb_pad = 0;
+	}
 
 	/*
 	 * Need a cursor.  Can't allocate until bb_level is filled in.
 	 */
-	mp = ip->i_mount;
 	cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork);
 	cur->bc_private.b.firstblock = *firstblock;
 	cur->bc_private.b.flist = flist;
@@ -3537,10 +3545,18 @@ xfs_bmap_extents_to_btree(
 	 * Fill in the child block.
 	 */
 	ablock = XFS_BUF_TO_BLOCK(abp);
-	ablock->bb_magic = cpu_to_be32(XFS_BMAP_MAGIC);
+	if (xfs_sb_version_hascrc(&mp->m_sb))
+		ablock->bb_magic = cpu_to_be32(XFS_BMAP_CRC_MAGIC);
+	else
+		ablock->bb_magic = cpu_to_be32(XFS_BMAP_MAGIC);
 	ablock->bb_level = 0;
 	ablock->bb_u.l.bb_leftsib = cpu_to_be64(NULLDFSBNO);
 	ablock->bb_u.l.bb_rightsib = cpu_to_be64(NULLDFSBNO);
+	if (xfs_sb_version_hascrc(&mp->m_sb)) {
+		ablock->bb_u.l.bb_blkno = cpu_to_be64(XFS_BUF_ADDR(abp));
+		uuid_copy(&ablock->bb_u.l.bb_uuid, &mp->m_sb.sb_uuid);
+		ablock->bb_u.l.bb_pad = 0;
+	}
 	arp = XFS_BMBT_REC_ADDR(mp, ablock, 1);
 	nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
 	for (cnt = i = 0; i < nextents; i++) {
@@ -3568,8 +3584,8 @@ xfs_bmap_extents_to_btree(
 	 * Do all this logging at the end so that
 	 * the root is at the right level.
 	 */
-	xfs_btree_log_block(cur, abp, XFS_BB_ALL_BITS);
 	xfs_btree_log_recs(cur, abp, 1, be16_to_cpu(ablock->bb_numrecs));
+	xfs_btree_log_block(cur, abp, XFS_BB_ALL_BITS);
 	ASSERT(*curp == NULL);
 	*curp = cur;
 	*logflagsp = XFS_ILOG_CORE | xfs_ilog_fbroot(whichfork);
@@ -3686,7 +3702,13 @@ xfs_bmap_local_to_extents(
 		ASSERT(args.fsbno != NULLFSBLOCK);
 		ASSERT(args.len == 1);
 		*firstblock = args.fsbno;
-		bp = xfs_btree_get_bufl(args.mp, tp, args.fsbno, 0);
+
+		bp = xfs_trans_get_buf(args.tp, args.mp->m_ddev_targp,
+				       XFS_FSB_TO_DADDR(args.mp, args.fsbno),
+				       args.mp->m_bsize, 0);
+		ASSERT(bp);
+		ASSERT(!XFS_BUF_GETERROR(bp));
+
 		memcpy((char *)XFS_BUF_PTR(bp), ifp->if_u1.if_data,
 			ifp->if_bytes);
 		xfs_trans_log_buf(tp, bp, 0, ifp->if_bytes - 1);
@@ -4562,11 +4584,21 @@ xfs_bmap_sanity_check(
 {
 	struct xfs_btree_block  *block = XFS_BUF_TO_BLOCK(bp);
 
-	if (be32_to_cpu(block->bb_magic) != XFS_BMAP_MAGIC ||
-	    be16_to_cpu(block->bb_level) != level ||
+	if (xfs_sb_version_hascrc(&mp->m_sb)) {
+		if (be32_to_cpu(block->bb_magic) != XFS_BMAP_CRC_MAGIC ||
+		    !uuid_equal(&block->bb_u.l.bb_uuid, &mp->m_sb.sb_uuid) ||
+		    block->bb_u.l.bb_blkno != cpu_to_be64(XFS_BUF_ADDR(bp)))
+			return 0;
+	} else {
+		if (be32_to_cpu(block->bb_magic) != XFS_BMAP_MAGIC)
+			return 0;
+	}
+
+	if (be16_to_cpu(block->bb_level) != level ||
 	    be16_to_cpu(block->bb_numrecs) == 0 ||
 	    be16_to_cpu(block->bb_numrecs) > mp->m_bmap_dmxr[level != 0])
 		return 0;
+
 	return 1;
 }
 
Index: xfs/fs/xfs/xfs_alloc_btree.c
===================================================================
--- xfs.orig/fs/xfs/xfs_alloc_btree.c	2009-02-09 19:05:49.038069167 +0100
+++ xfs/fs/xfs/xfs_alloc_btree.c	2009-02-09 19:15:42.855068736 +0100
@@ -474,6 +474,8 @@ xfs_allocbt_init_cursor(
 	cur->bc_ops = &xfs_allocbt_ops;
 	if (btnum == XFS_BTNUM_CNT)
 		cur->bc_flags = XFS_BTREE_LASTREC_UPDATE;
+	if (xfs_sb_version_hascrc(&mp->m_sb))
+		cur->bc_flags |= XFS_BTREE_CRC_BLOCKS;
 
 	cur->bc_private.a.agbp = agbp;
 	cur->bc_private.a.agno = agno;
Index: xfs/fs/xfs/xfs_ialloc_btree.c
===================================================================
--- xfs.orig/fs/xfs/xfs_ialloc_btree.c	2009-02-09 19:05:49.043068895 +0100
+++ xfs/fs/xfs/xfs_ialloc_btree.c	2009-02-09 19:15:42.857069060 +0100
@@ -359,6 +359,8 @@ xfs_inobt_init_cursor(
 	cur->bc_blocklog = mp->m_sb.sb_blocklog;
 
 	cur->bc_ops = &xfs_inobt_ops;
+	if (xfs_sb_version_hascrc(&mp->m_sb))
+		cur->bc_flags |= XFS_BTREE_CRC_BLOCKS;
 
 	cur->bc_private.a.agbp = agbp;
 	cur->bc_private.a.agno = agno;
Index: xfs/fs/xfs/xfs_fsops.c
===================================================================
--- xfs.orig/fs/xfs/xfs_fsops.c	2009-02-09 19:05:49.047068705 +0100
+++ xfs/fs/xfs/xfs_fsops.c	2009-02-09 19:15:42.860069581 +0100
@@ -253,11 +253,19 @@ xfs_growfs_data_private(
 			BTOBB(mp->m_sb.sb_blocksize), 0);
 		block = XFS_BUF_TO_BLOCK(bp);
 		memset(block, 0, mp->m_sb.sb_blocksize);
-		block->bb_magic = cpu_to_be32(XFS_ABTB_MAGIC);
 		block->bb_level = 0;
 		block->bb_numrecs = cpu_to_be16(1);
 		block->bb_u.s.bb_leftsib = cpu_to_be32(NULLAGBLOCK);
 		block->bb_u.s.bb_rightsib = cpu_to_be32(NULLAGBLOCK);
+		if (xfs_sb_version_hascrc(&mp->m_sb)) {
+			block->bb_magic = cpu_to_be32(XFS_ABTB_CRC_MAGIC);
+			block->bb_u.s.bb_blkno = cpu_to_be64(XFS_BUF_ADDR(bp));
+			uuid_copy(&block->bb_u.s.bb_uuid, &mp->m_sb.sb_uuid);
+			block->bb_u.s.bb_pad = 0;
+			xfs_buf_set_io_callback(bp, xfs_btree_sblock_calc_crc);
+		} else {
+			block->bb_magic = cpu_to_be32(XFS_ABTB_MAGIC);
+		}
 		arec = XFS_ALLOC_REC_ADDR(mp, block, 1);
 		arec->ar_startblock = cpu_to_be32(XFS_PREALLOC_BLOCKS(mp));
 		arec->ar_blockcount = cpu_to_be32(
@@ -274,11 +282,19 @@ xfs_growfs_data_private(
 			BTOBB(mp->m_sb.sb_blocksize), 0);
 		block = XFS_BUF_TO_BLOCK(bp);
 		memset(block, 0, mp->m_sb.sb_blocksize);
-		block->bb_magic = cpu_to_be32(XFS_ABTC_MAGIC);
 		block->bb_level = 0;
 		block->bb_numrecs = cpu_to_be16(1);
 		block->bb_u.s.bb_leftsib = cpu_to_be32(NULLAGBLOCK);
 		block->bb_u.s.bb_rightsib = cpu_to_be32(NULLAGBLOCK);
+		if (xfs_sb_version_hascrc(&mp->m_sb)) {
+			block->bb_magic = cpu_to_be32(XFS_ABTC_CRC_MAGIC);
+			block->bb_u.s.bb_blkno = cpu_to_be64(XFS_BUF_ADDR(bp));
+			uuid_copy(&block->bb_u.s.bb_uuid, &mp->m_sb.sb_uuid);
+			block->bb_u.s.bb_pad = 0;
+			xfs_buf_set_io_callback(bp, xfs_btree_sblock_calc_crc);
+		} else {
+			block->bb_magic = cpu_to_be32(XFS_ABTC_MAGIC);
+		}
 		arec = XFS_ALLOC_REC_ADDR(mp, block, 1);
 		arec->ar_startblock = cpu_to_be32(XFS_PREALLOC_BLOCKS(mp));
 		arec->ar_blockcount = cpu_to_be32(
@@ -296,11 +312,19 @@ xfs_growfs_data_private(
 			BTOBB(mp->m_sb.sb_blocksize), 0);
 		block = XFS_BUF_TO_BLOCK(bp);
 		memset(block, 0, mp->m_sb.sb_blocksize);
-		block->bb_magic = cpu_to_be32(XFS_IBT_MAGIC);
 		block->bb_level = 0;
 		block->bb_numrecs = 0;
 		block->bb_u.s.bb_leftsib = cpu_to_be32(NULLAGBLOCK);
 		block->bb_u.s.bb_rightsib = cpu_to_be32(NULLAGBLOCK);
+		if (xfs_sb_version_hascrc(&mp->m_sb)) {
+			block->bb_magic = cpu_to_be32(XFS_IBT_CRC_MAGIC);
+			block->bb_u.s.bb_blkno = cpu_to_be64(XFS_BUF_ADDR(bp));
+			uuid_copy(&block->bb_u.s.bb_uuid, &mp->m_sb.sb_uuid);
+			block->bb_u.s.bb_pad = 0;
+			xfs_buf_set_io_callback(bp, xfs_btree_sblock_calc_crc);
+		} else {
+			block->bb_magic = cpu_to_be32(XFS_IBT_MAGIC);
+		}
 		error = xfs_bwrite(mp, bp);
 		if (error) {
 			goto error0;
Index: xfs/fs/xfs/xfs_alloc_btree.h
===================================================================
--- xfs.orig/fs/xfs/xfs_alloc_btree.h	2009-02-09 19:05:49.051069843 +0100
+++ xfs/fs/xfs/xfs_alloc_btree.h	2009-02-09 19:15:42.862069766 +0100
@@ -31,8 +31,10 @@ struct xfs_mount;
  * by blockcount and blockno.  All blocks look the same to make the code
  * simpler; if we have time later, we'll make the optimizations.
  */
-#define	XFS_ABTB_MAGIC	0x41425442	/* 'ABTB' for bno tree */
-#define	XFS_ABTC_MAGIC	0x41425443	/* 'ABTC' for cnt tree */
+#define	XFS_ABTB_MAGIC		0x41425442	/* 'ABTB' for bno tree */
+#define	XFS_ABTB_CRC_MAGIC	0x4142544a
+#define	XFS_ABTC_MAGIC		0x41425443	/* 'ABTC' for cnt tree */
+#define	XFS_ABTC_CRC_MAGIC	0x4142544b
 
 /*
  * Data record/key structure
@@ -73,10 +75,11 @@ typedef __be32 xfs_alloc_ptr_t;
 
 /*
  * Btree block header size depends on a superblock flag.
- *
- * (not quite yet, but soon)
  */
-#define XFS_ALLOC_BLOCK_LEN(mp)	XFS_BTREE_SBLOCK_LEN
+#define XFS_ALLOC_BLOCK_LEN(mp) \
+	(xfs_sb_version_hascrc(&((mp)->m_sb)) ? \
+	 XFS_BTREE_SBLOCK_LEN + XFS_BTREE_CRCBLOCK_ADD : \
+	 XFS_BTREE_SBLOCK_LEN)
 
 /*
  * Record, key, and pointer address macros for btree blocks.
Index: xfs/fs/xfs/xfs_ialloc_btree.h
===================================================================
--- xfs.orig/fs/xfs/xfs_ialloc_btree.h	2009-02-09 19:05:49.055069304 +0100
+++ xfs/fs/xfs/xfs_ialloc_btree.h	2009-02-09 19:15:42.866069437 +0100
@@ -29,7 +29,8 @@ struct xfs_mount;
 /*
  * There is a btree for the inode map per allocation group.
  */
-#define	XFS_IBT_MAGIC	0x49414254	/* 'IABT' */
+#define	XFS_IBT_MAGIC		0x49414254	/* 'IABT' */
+#define	XFS_IBT_CRC_MAGIC	0x4941425c
 
 typedef	__uint64_t	xfs_inofree_t;
 #define	XFS_INODES_PER_CHUNK		(NBBY * sizeof(xfs_inofree_t))
@@ -76,10 +77,11 @@ typedef __be32 xfs_inobt_ptr_t;
 
 /*
  * Btree block header size depends on a superblock flag.
- *
- * (not quite yet, but soon)
  */
-#define XFS_INOBT_BLOCK_LEN(mp)	XFS_BTREE_SBLOCK_LEN
+#define XFS_INOBT_BLOCK_LEN(mp) \
+	(xfs_sb_version_hascrc(&((mp)->m_sb)) ? \
+	 XFS_BTREE_SBLOCK_LEN + XFS_BTREE_CRCBLOCK_ADD : \
+	 XFS_BTREE_SBLOCK_LEN)
 
 /*
  * Record, key, and pointer address macros for btree blocks.
Index: xfs/fs/xfs/xfs_log_recover.c
===================================================================
--- xfs.orig/fs/xfs/xfs_log_recover.c	2009-02-09 19:15:38.648943978 +0100
+++ xfs/fs/xfs/xfs_log_recover.c	2009-02-09 19:15:42.873069001 +0100
@@ -31,6 +31,7 @@
 #include "xfs_bmap_btree.h"
 #include "xfs_alloc_btree.h"
 #include "xfs_ialloc_btree.h"
+#include "xfs_btree.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
@@ -1980,6 +1981,19 @@ xlog_recover_do_reg_buffer(
 		bit += nbits;
 	}
 
+	switch (be32_to_cpu(*(__be32 *)XFS_BUF_PTR(bp))) {
+	case XFS_ABTB_CRC_MAGIC:
+	case XFS_ABTC_CRC_MAGIC:
+	case XFS_IBT_CRC_MAGIC:
+		xfs_btree_sblock_calc_crc(bp);
+		break;
+	case XFS_BMAP_CRC_MAGIC:
+		xfs_btree_lblock_calc_crc(bp);
+		break;
+	default:
+		break;
+	}
+
 	/* Shouldn't be any more regions */
 	ASSERT(i == item->ri_total);
 }

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

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 07/13] xfs: add CRC checks to the superblock
  2009-02-10 20:22 [PATCH 00/13] Updated CRC patches Christoph Hellwig
                   ` (5 preceding siblings ...)
  2009-02-10 20:22 ` [PATCH 06/13] xfs: add support for large btree blocks Christoph Hellwig
@ 2009-02-10 20:22 ` Christoph Hellwig
  2009-02-10 20:22 ` [PATCH 08/13] xfs: add CRC checks to the AGF Christoph Hellwig
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 22+ messages in thread
From: Christoph Hellwig @ 2009-02-10 20:22 UTC (permalink / raw)
  To: xfs; +Cc: Dave Chinner

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

[hch: minor adaptions]


Signed-off-by: Dave Chinner <dgc@sgi.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>

Index: xfs/fs/xfs/xfs_mount.c
===================================================================
--- xfs.orig/fs/xfs/xfs_mount.c	2009-02-09 19:15:40.377949194 +0100
+++ xfs/fs/xfs/xfs_mount.c	2009-02-09 19:15:45.187943691 +0100
@@ -44,6 +44,7 @@
 #include "xfs_quota.h"
 #include "xfs_fsops.h"
 #include "xfs_utils.h"
+#include "xfs_cksum.h"
 
 STATIC int	xfs_uuid_mount(xfs_mount_t *);
 STATIC void	xfs_unmountfs_wait(xfs_mount_t *);
@@ -118,6 +119,8 @@ static const struct {
     { offsetof(xfs_sb_t, sb_logsunit),	 0 },
     { offsetof(xfs_sb_t, sb_features2),	 0 },
     { offsetof(xfs_sb_t, sb_bad_features2), 0 },
+    { offsetof(xfs_sb_t, sb_crc),	 0 },
+    { offsetof(xfs_sb_t, sb_pad),	 0 },
     { sizeof(xfs_sb_t),			 0 }
 };
 
@@ -408,6 +411,7 @@ xfs_sb_from_disk(
 	to->sb_logsunit = be32_to_cpu(from->sb_logsunit);
 	to->sb_features2 = be32_to_cpu(from->sb_features2);
 	to->sb_bad_features2 = be32_to_cpu(from->sb_bad_features2);
+	to->sb_crc = be32_to_cpu(from->sb_crc);
 }
 
 /*
@@ -464,6 +468,24 @@ xfs_sb_to_disk(
 }
 
 /*
+ * Calculate the superblock CRC and stuff it in the buffer.
+ *
+ * We get called here just before the superblock is written
+ * to disk. We should also do some validity checking here.
+ *
+ * We CRC the entire superblock sector, not just the bits we use
+ * so that changes in structure size as features are included do
+ * not invalidate CRCs.
+ */
+void
+xfs_sb_calc_crc(
+	struct xfs_buf	*bp)
+{
+	xfs_update_cksum(XFS_BUF_PTR(bp), XFS_BUF_SIZE(bp),
+			 offsetof(struct xfs_sb, sb_crc));
+}
+
+/*
  * xfs_readsb
  *
  * Does the initial read of the superblock.
@@ -474,6 +496,7 @@ xfs_readsb(xfs_mount_t *mp, int flags)
 	unsigned int	sector_size;
 	unsigned int	extra_flags;
 	xfs_buf_t	*bp;
+	xfs_sb_t	*sbp = &mp->m_sb;
 	int		error;
 
 	ASSERT(mp->m_sb_bp == NULL);
@@ -503,7 +526,25 @@ xfs_readsb(xfs_mount_t *mp, int flags)
 	 */
 	xfs_sb_from_disk(&mp->m_sb, XFS_BUF_TO_SBP(bp));
 
-	error = xfs_mount_validate_sb(mp, &(mp->m_sb), flags);
+	/*
+	 * If the superblock has the CRC feature bit set or
+	 * the CRC field is non-null, check that the CRC is valid.
+	 * We check the CRC field is non-null because a single bit
+	 * error could clear the feature bit and unused parts of
+	 * the superblock are supposed to be zero. Hence a non-null
+	 * crc field indicates that we've potentially lost a feature
+	 * bit and we should check it anyway.
+	 */
+	if (xfs_sb_version_hascrc(sbp) || sbp->sb_crc != 0) {
+		if (!xfs_verify_cksum(XFS_BUF_PTR(bp), sbp->sb_sectsize,
+				      offsetof(struct xfs_sb, sb_crc))) {
+			xfs_fs_mount_cmn_err(flags, "SB CRC check failed");
+			error = EFSCORRUPTED;
+			goto fail;
+		}
+	}
+
+	error = xfs_mount_validate_sb(mp, sbp, flags);
 	if (error) {
 		xfs_fs_mount_cmn_err(flags, "SB validate failed");
 		goto fail;
@@ -512,10 +553,10 @@ xfs_readsb(xfs_mount_t *mp, int flags)
 	/*
 	 * We must be able to do sector-sized and sector-aligned IO.
 	 */
-	if (sector_size > mp->m_sb.sb_sectsize) {
+	if (sector_size > sbp->sb_sectsize) {
 		xfs_fs_mount_cmn_err(flags,
 			"device supports only %u byte sectors (not %u)",
-			sector_size, mp->m_sb.sb_sectsize);
+			sector_size, sbp->sb_sectsize);
 		error = ENOSYS;
 		goto fail;
 	}
@@ -524,10 +565,10 @@ xfs_readsb(xfs_mount_t *mp, int flags)
 	 * If device sector size is smaller than the superblock size,
 	 * re-read the superblock so the buffer is correctly sized.
 	 */
-	if (sector_size < mp->m_sb.sb_sectsize) {
+	if (sector_size < sbp->sb_sectsize) {
 		XFS_BUF_UNMANAGE(bp);
 		xfs_buf_relse(bp);
-		sector_size = mp->m_sb.sb_sectsize;
+		sector_size = sbp->sb_sectsize;
 		bp = xfs_buf_read_flags(mp->m_ddev_targp, XFS_SB_DADDR,
 					BTOBB(sector_size), extra_flags);
 		if (!bp || XFS_BUF_ISERROR(bp)) {
@@ -543,11 +584,13 @@ xfs_readsb(xfs_mount_t *mp, int flags)
 	xfs_icsb_reinit_counters(mp);
 
 	mp->m_sb_bp = bp;
+	if (xfs_sb_version_hascrc(sbp))
+		xfs_buf_set_io_callback(bp, xfs_sb_calc_crc);
 	xfs_buf_relse(bp);
 	ASSERT(XFS_BUF_VALUSEMA(bp) > 0);
 	return 0;
 
- fail:
+fail:
 	if (bp) {
 		XFS_BUF_UNMANAGE(bp);
 		xfs_buf_relse(bp);
Index: xfs/fs/xfs/xfs_sb.h
===================================================================
--- xfs.orig/fs/xfs/xfs_sb.h	2009-02-09 19:15:40.363974092 +0100
+++ xfs/fs/xfs/xfs_sb.h	2009-02-09 19:15:45.192944467 +0100
@@ -160,7 +160,10 @@ typedef struct xfs_sb {
 	 */
 	__uint32_t	sb_bad_features2;
 
+	__uint32_t	sb_crc;		/* superblock crc */
+
 	/* must be padded to 64 bit alignment */
+	__uint32_t	sb_pad;
 } xfs_sb_t;
 
 /*
@@ -228,9 +231,12 @@ typedef struct xfs_dsb {
 	 * for features2 bits. Easiest just to mark it bad and not use
 	 * it for anything else.
 	 */
-	__be32	sb_bad_features2;
+	__be32		sb_bad_features2;
+
+	__be32		sb_crc;		/* superblock crc */
 
 	/* must be padded to 64 bit alignment */
+	__be32		sb_pad;
 } xfs_dsb_t;
 
 /*
@@ -249,7 +255,7 @@ typedef enum {
 	XFS_SBS_GQUOTINO, XFS_SBS_QFLAGS, XFS_SBS_FLAGS, XFS_SBS_SHARED_VN,
 	XFS_SBS_INOALIGNMT, XFS_SBS_UNIT, XFS_SBS_WIDTH, XFS_SBS_DIRBLKLOG,
 	XFS_SBS_LOGSECTLOG, XFS_SBS_LOGSECTSIZE, XFS_SBS_LOGSUNIT,
-	XFS_SBS_FEATURES2, XFS_SBS_BAD_FEATURES2,
+	XFS_SBS_FEATURES2, XFS_SBS_BAD_FEATURES2, XFS_SBS_CRC, XFS_SBS_PAD,
 	XFS_SBS_FIELDCOUNT
 } xfs_sb_field_t;
 
@@ -275,6 +281,8 @@ typedef enum {
 #define XFS_SB_FDBLOCKS		XFS_SB_MVAL(FDBLOCKS)
 #define XFS_SB_FEATURES2	XFS_SB_MVAL(FEATURES2)
 #define XFS_SB_BAD_FEATURES2	XFS_SB_MVAL(BAD_FEATURES2)
+#define XFS_SB_CRC		XFS_SB_MVAL(CRC)
+#define XFS_SB_PAD		XFS_SB_MVAL(PAD)
 #define	XFS_SB_NUM_BITS		((int)XFS_SBS_FIELDCOUNT)
 #define	XFS_SB_ALL_BITS		((1LL << XFS_SB_NUM_BITS) - 1)
 #define	XFS_SB_MOD_BITS		\
Index: xfs/fs/xfs/xfs_trans.c
===================================================================
--- xfs.orig/fs/xfs/xfs_trans.c	2009-02-09 19:05:48.429078156 +0100
+++ xfs/fs/xfs/xfs_trans.c	2009-02-09 19:15:45.194049007 +0100
@@ -44,6 +44,7 @@
 #include "xfs_trans_priv.h"
 #include "xfs_trans_space.h"
 #include "xfs_inode_item.h"
+#include "xfs_cksum.h"
 
 
 STATIC void	xfs_trans_apply_sb_deltas(xfs_trans_t *);
Index: xfs/fs/xfs/xfs_mount.h
===================================================================
--- xfs.orig/fs/xfs/xfs_mount.h	2009-02-09 19:15:35.584944583 +0100
+++ xfs/fs/xfs/xfs_mount.h	2009-02-09 19:15:45.194049007 +0100
@@ -521,6 +521,7 @@ extern struct xfs_dmops xfs_dmcore_xfs;
 
 #endif	/* __KERNEL__ */
 
+extern void	xfs_sb_calc_crc(struct xfs_buf	*);
 extern void	xfs_mod_sb(struct xfs_trans *, __int64_t);
 extern xfs_agnumber_t	xfs_initialize_perag(struct xfs_mount *, xfs_agnumber_t);
 extern void	xfs_sb_from_disk(struct xfs_sb *, struct xfs_dsb *);
Index: xfs/fs/xfs/xfs_log_recover.c
===================================================================
--- xfs.orig/fs/xfs/xfs_log_recover.c	2009-02-09 19:15:42.873069001 +0100
+++ xfs/fs/xfs/xfs_log_recover.c	2009-02-09 19:15:45.196071052 +0100
@@ -1990,6 +1990,9 @@ xlog_recover_do_reg_buffer(
 	case XFS_BMAP_CRC_MAGIC:
 		xfs_btree_lblock_calc_crc(bp);
 		break;
+	case XFS_SB_MAGIC:
+		xfs_sb_calc_crc(bp);
+		break;
 	default:
 		break;
 	}

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

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 08/13] xfs: add CRC checks to the AGF
  2009-02-10 20:22 [PATCH 00/13] Updated CRC patches Christoph Hellwig
                   ` (6 preceding siblings ...)
  2009-02-10 20:22 ` [PATCH 07/13] xfs: add CRC checks to the superblock Christoph Hellwig
@ 2009-02-10 20:22 ` Christoph Hellwig
  2009-02-10 20:22 ` [PATCH 09/13] xfs: add CRC checks to the AGI Christoph Hellwig
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 22+ messages in thread
From: Christoph Hellwig @ 2009-02-10 20:22 UTC (permalink / raw)
  To: xfs; +Cc: Dave Chinner

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

[hch: minor adaptions]


Signed-off-by: Dave Chinner <dgc@sgi.com>
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:05:48.120069296 +0100
+++ xfs/fs/xfs/xfs_ag.h	2009-02-09 19:15:46.916949727 +0100
@@ -69,6 +69,8 @@ typedef struct xfs_agf {
 	__be32		agf_freeblks;	/* total free blocks */
 	__be32		agf_longest;	/* longest free space */
 	__be32		agf_btreeblks;	/* # of blocks held in AGF btrees */
+	__be32		agf_crc;	/* crc of agf sector */
+	uuid_t		agf_uuid;	/* uuid of filesystem */
 } xfs_agf_t;
 
 #define	XFS_AGF_MAGICNUM	0x00000001
@@ -91,6 +93,7 @@ typedef struct xfs_agf {
 #define	XFS_AGF_BLOCK(mp)	XFS_HDR_BLOCK(mp, XFS_AGF_DADDR(mp))
 #define	XFS_BUF_TO_AGF(bp)	((xfs_agf_t *)XFS_BUF_PTR(bp))
 
+extern void xfs_agf_calc_crc(struct xfs_buf *bp);
 extern int xfs_read_agf(struct xfs_mount *mp, struct xfs_trans *tp,
 			xfs_agnumber_t agno, int flags, struct xfs_buf **bpp);
 
Index: xfs/fs/xfs/xfs_fsops.c
===================================================================
--- xfs.orig/fs/xfs/xfs_fsops.c	2009-02-09 19:15:42.860069581 +0100
+++ xfs/fs/xfs/xfs_fsops.c	2009-02-09 19:15:46.917943848 +0100
@@ -217,6 +217,10 @@ xfs_growfs_data_private(
 		tmpsize = agsize - XFS_PREALLOC_BLOCKS(mp);
 		agf->agf_freeblks = cpu_to_be32(tmpsize);
 		agf->agf_longest = cpu_to_be32(tmpsize);
+		if (xfs_sb_version_hascrc(&mp->m_sb)) {
+			uuid_copy(&agf->agf_uuid, &mp->m_sb.sb_uuid);
+			xfs_buf_set_io_callback(bp, xfs_agf_calc_crc);
+		}
 		error = xfs_bwrite(mp, bp);
 		if (error) {
 			goto error0;
Index: xfs/fs/xfs/xfs_alloc.c
===================================================================
--- xfs.orig/fs/xfs/xfs_alloc.c	2009-02-09 19:05:48.190069960 +0100
+++ xfs/fs/xfs/xfs_alloc.c	2009-02-09 19:15:46.920944300 +0100
@@ -38,6 +38,7 @@
 #include "xfs_ialloc.h"
 #include "xfs_alloc.h"
 #include "xfs_error.h"
+#include "xfs_cksum.h"
 
 
 #define XFS_ABSDIFF(a,b)	(((a) <= (b)) ? ((b) - (a)) : ((a) - (b)))
@@ -2230,6 +2231,23 @@ xfs_alloc_put_freelist(
 }
 
 /*
+ * Calculate CRC on AGF and stuff it into the structure.
+ *
+ * We CRC the entire AGF 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 AGF is written to disk. We should
+ * also do some validity checking here.
+ */
+void
+xfs_agf_calc_crc(
+	struct xfs_buf		*bp)
+{
+	xfs_update_cksum(XFS_BUF_PTR(bp), XFS_BUF_SIZE(bp),
+			 offsetof(struct xfs_agf, agf_crc));
+}
+
+/*
  * Read in the allocation group header (free/alloc section).
  */
 int					/* error */
@@ -2258,6 +2276,22 @@ xfs_read_agf(
 	agf = XFS_BUF_TO_AGF(*bpp);
 
 	/*
+	 * 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(*bpp) || XFS_BUF_ISDELAYWRITE(*bpp))) {
+		if (!xfs_verify_cksum(XFS_BUF_PTR(*bpp), XFS_BUF_SIZE(*bpp),
+				      offsetof(struct xfs_agf, agf_crc)) ||
+		    !uuid_equal(&agf->agf_uuid, &mp->m_sb.sb_uuid)) {
+			XFS_CORRUPTION_ERROR("xfs_read_agf crc",
+					XFS_ERRLEVEL_LOW, mp, agf);
+			xfs_trans_brelse(tp, *bpp);
+			return XFS_ERROR(EFSCORRUPTED);
+		}
+	}
+
+	/*
 	 * Validate the magic number of the agf block.
 	 */
 	agf_ok =
@@ -2280,6 +2314,9 @@ xfs_read_agf(
 	}
 
 	XFS_BUF_SET_VTYPE_REF(*bpp, B_FS_AGF, XFS_AGF_REF);
+
+	if (xfs_sb_version_hascrc(&mp->m_sb))
+		xfs_buf_set_io_callback(*bpp, xfs_agf_calc_crc);
 	return 0;
 }
 
Index: xfs/fs/xfs/xfs_log_recover.c
===================================================================
--- xfs.orig/fs/xfs/xfs_log_recover.c	2009-02-09 19:15:45.196071052 +0100
+++ xfs/fs/xfs/xfs_log_recover.c	2009-02-09 19:15:46.924974841 +0100
@@ -1993,6 +1993,9 @@ xlog_recover_do_reg_buffer(
 	case XFS_SB_MAGIC:
 		xfs_sb_calc_crc(bp);
 		break;
+	case XFS_AGF_MAGIC:
+		xfs_agf_calc_crc(bp);
+		break;
 	default:
 		break;
 	}

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

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 09/13] xfs: add CRC checks to the AGI
  2009-02-10 20:22 [PATCH 00/13] Updated CRC patches Christoph Hellwig
                   ` (7 preceding siblings ...)
  2009-02-10 20:22 ` [PATCH 08/13] xfs: add CRC checks to the AGF Christoph Hellwig
@ 2009-02-10 20:22 ` Christoph Hellwig
  2009-02-10 20:22 ` [PATCH 10/13] xfs: add CRC checks to the AGFL Christoph Hellwig
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 22+ messages in thread
From: Christoph Hellwig @ 2009-02-10 20:22 UTC (permalink / raw)
  To: xfs; +Cc: Dave Chinner

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

[hch: minor adaptions]


Signed-off-by: Dave Chinner <dgc@sgi.com>
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:46.916949727 +0100
+++ xfs/fs/xfs/xfs_ag.h	2009-02-09 19:15:48.966944136 +0100
@@ -126,6 +126,8 @@ typedef struct xfs_agi {
 	 * still being referenced.
 	 */
 	__be32		agi_unlinked[XFS_AGI_UNLINKED_BUCKETS];
+	__be32		agi_crc;	/* crc of agi sector */
+	uuid_t		agi_uuid;	/* uuid of filesystem */
 } xfs_agi_t;
 
 #define	XFS_AGI_MAGICNUM	0x00000001
@@ -139,6 +141,9 @@ typedef struct xfs_agi {
 #define	XFS_AGI_NEWINO		0x00000100
 #define	XFS_AGI_DIRINO		0x00000200
 #define	XFS_AGI_UNLINKED	0x00000400
+/*
+ * XXX(hch): update for the CRC additions?  It's unused anyway..
+ */
 #define	XFS_AGI_NUM_BITS	11
 #define	XFS_AGI_ALL_BITS	((1 << XFS_AGI_NUM_BITS) - 1)
 
@@ -147,6 +152,7 @@ typedef struct xfs_agi {
 #define	XFS_AGI_BLOCK(mp)	XFS_HDR_BLOCK(mp, XFS_AGI_DADDR(mp))
 #define	XFS_BUF_TO_AGI(bp)	((xfs_agi_t *)XFS_BUF_PTR(bp))
 
+extern void xfs_agi_calc_crc(struct xfs_buf *bp);
 extern int xfs_read_agi(struct xfs_mount *mp, struct xfs_trans *tp,
 				xfs_agnumber_t agno, struct xfs_buf **bpp);
 
Index: xfs/fs/xfs/xfs_fsops.c
===================================================================
--- xfs.orig/fs/xfs/xfs_fsops.c	2009-02-09 19:15:46.917943848 +0100
+++ xfs/fs/xfs/xfs_fsops.c	2009-02-09 19:15:48.966944136 +0100
@@ -245,6 +245,10 @@ xfs_growfs_data_private(
 		agi->agi_dirino = cpu_to_be32(NULLAGINO);
 		for (bucket = 0; bucket < XFS_AGI_UNLINKED_BUCKETS; bucket++)
 			agi->agi_unlinked[bucket] = cpu_to_be32(NULLAGINO);
+		if (xfs_sb_version_hascrc(&mp->m_sb)) {
+			uuid_copy(&agi->agi_uuid, &mp->m_sb.sb_uuid);
+			xfs_buf_set_io_callback(bp, xfs_agi_calc_crc);
+		}
 		error = xfs_bwrite(mp, bp);
 		if (error) {
 			goto error0;
Index: xfs/fs/xfs/xfs_ialloc.c
===================================================================
--- xfs.orig/fs/xfs/xfs_ialloc.c	2009-02-09 19:05:48.022069819 +0100
+++ xfs/fs/xfs/xfs_ialloc.c	2009-02-09 19:15:48.968944600 +0100
@@ -40,6 +40,7 @@
 #include "xfs_rtalloc.h"
 #include "xfs_error.h"
 #include "xfs_bmap.h"
+#include "xfs_cksum.h"
 
 
 /*
@@ -1455,6 +1456,24 @@ xfs_check_agi_unlinked(
 #endif
 
 /*
+ * Calculate CRC on AGI and stuff it into the structure.
+ *
+ * We CRC the entire AGI 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 AGI is written to disk. We should
+ * also do some validity checking here.
+ */
+void
+xfs_agi_calc_crc(
+	xfs_buf_t	*bp)
+{
+	xfs_update_cksum(XFS_BUF_PTR(bp), XFS_BUF_SIZE(bp),
+			 offsetof(struct xfs_agi, agi_crc));
+
+}
+
+/*
  * Read in the allocation group header (inode allocation section)
  */
 int
@@ -1464,6 +1483,7 @@ xfs_read_agi(
 	xfs_agnumber_t		agno,	/* allocation group number */
 	struct xfs_buf		**bpp)	/* allocation group hdr buf */
 {
+	struct xfs_buf		*bp;
 	struct xfs_agi		*agi;	/* allocation group header */
 	int			agi_ok;	/* agi is consistent */
 	int			error;
@@ -1472,12 +1492,28 @@ xfs_read_agi(
 
 	error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
 			XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)),
-			XFS_FSS_TO_BB(mp, 1), 0, bpp);
+			XFS_FSS_TO_BB(mp, 1), 0, &bp);
 	if (error)
 		return error;
 
-	ASSERT(*bpp && !XFS_BUF_GETERROR(*bpp));
-	agi = XFS_BUF_TO_AGI(*bpp);
+	ASSERT(bp && !XFS_BUF_GETERROR(bp));
+	agi = XFS_BUF_TO_AGI(bp);
+
+	/*
+	 * Validate the CRC of the AGI 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))) {
+		if (!xfs_verify_cksum(XFS_BUF_PTR(bp), XFS_BUF_SIZE(bp),
+				      offsetof(struct xfs_agi, agi_crc)) ||
+		    !uuid_equal(&agi->agi_uuid, &mp->m_sb.sb_uuid)) {
+			XFS_CORRUPTION_ERROR("xfs_read_agi crc",
+					XFS_ERRLEVEL_LOW, mp, agi);
+			xfs_trans_brelse(tp, bp);
+			return XFS_ERROR(EFSCORRUPTED);
+		}
+	}
 
 	/*
 	 * Validate the magic number of the agi block.
@@ -1489,13 +1525,18 @@ xfs_read_agi(
 			XFS_RANDOM_IALLOC_READ_AGI))) {
 		XFS_CORRUPTION_ERROR("xfs_read_agi", XFS_ERRLEVEL_LOW,
 				     mp, agi);
-		xfs_trans_brelse(tp, *bpp);
+		xfs_trans_brelse(tp, bp);
 		return XFS_ERROR(EFSCORRUPTED);
 	}
 
-	XFS_BUF_SET_VTYPE_REF(*bpp, B_FS_AGI, XFS_AGI_REF);
+	XFS_BUF_SET_VTYPE_REF(bp, B_FS_AGI, XFS_AGI_REF);
 
 	xfs_check_agi_unlinked(agi);
+
+	if (xfs_sb_version_hascrc(&mp->m_sb))
+		xfs_buf_set_io_callback(bp, xfs_agi_calc_crc);
+
+	*bpp = bp;
 	return 0;
 }
 
Index: xfs/fs/xfs/xfs_log_recover.c
===================================================================
--- xfs.orig/fs/xfs/xfs_log_recover.c	2009-02-09 19:15:46.924974841 +0100
+++ xfs/fs/xfs/xfs_log_recover.c	2009-02-09 19:15:48.970972860 +0100
@@ -1996,6 +1996,9 @@ xlog_recover_do_reg_buffer(
 	case XFS_AGF_MAGIC:
 		xfs_agf_calc_crc(bp);
 		break;
+ 	case XFS_AGI_MAGIC:
+		xfs_agi_calc_crc(bp);
+		break;
 	default:
 		break;
 	}

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

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 10/13] xfs: add CRC checks to the AGFL
  2009-02-10 20:22 [PATCH 00/13] Updated CRC patches Christoph Hellwig
                   ` (8 preceding siblings ...)
  2009-02-10 20:22 ` [PATCH 09/13] xfs: add CRC checks to the AGI Christoph Hellwig
@ 2009-02-10 20:22 ` Christoph Hellwig
  2009-02-11  7:54   ` Dave Chinner
  2009-02-10 20:22 ` [PATCH 11/13] xfs: add CRC checks to the log Christoph Hellwig
                   ` (2 subsequent siblings)
  12 siblings, 1 reply; 22+ messages in thread
From: Christoph Hellwig @ 2009-02-10 20:22 UTC (permalink / raw)
  To: xfs

[-- 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

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 11/13] xfs: add CRC checks to the log
  2009-02-10 20:22 [PATCH 00/13] Updated CRC patches Christoph Hellwig
                   ` (9 preceding siblings ...)
  2009-02-10 20:22 ` [PATCH 10/13] xfs: add CRC checks to the AGFL Christoph Hellwig
@ 2009-02-10 20:22 ` Christoph Hellwig
  2009-02-10 20:22 ` [PATCH 12/13] xfs: add version 3 inode format with CRCs Christoph Hellwig
  2009-02-10 20:22 ` [PATCH 13/13] xfs: add CRC checks for quota blocks Christoph Hellwig
  12 siblings, 0 replies; 22+ messages in thread
From: Christoph Hellwig @ 2009-02-10 20:22 UTC (permalink / raw)
  To: xfs

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

Implement CRCs for the log buffers.  We re-use a field in
struct xlog_rec_header that was used for a weak checksum of the
log buffer payload in debug builds before.

The new checksumming uses the same crc32c checksum we use elsewhere
in XFS, and also protects the record header and addition cycle data.

Due to this there are some interesting changes in xlog_sync, as we
need to do the cycle wrapping for the split buffer case much earlier,
as we would touch the buffer after generating the checksum otherwise.

Based on a patch from Dave Chinner with lots of changes.


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

Index: xfs/fs/xfs/xfs_log_priv.h
===================================================================
--- xfs.orig/fs/xfs/xfs_log_priv.h	2009-02-10 19:22:43.915068626 +0100
+++ xfs/fs/xfs/xfs_log_priv.h	2009-02-10 19:45:54.102069909 +0100
@@ -142,7 +142,7 @@ static inline uint xlog_get_client_id(__
 /*
  * Flags for log structure
  */
-#define XLOG_CHKSUM_MISMATCH	0x1	/* used only during recovery */
+#define XLOG_CRC_MISMATCH	0x1	/* used only during recovery */
 #define XLOG_ACTIVE_RECOVERY	0x2	/* in the middle of recovery */
 #define	XLOG_RECOVERY_NEEDED	0x4	/* log was recovered */
 #define XLOG_IO_ERROR		0x8	/* log hit an I/O error, and being
@@ -294,7 +294,7 @@ typedef struct xlog_rec_header {
 	__be32	  h_len;	/* len in bytes; should be 64-bit aligned: 4 */
 	__be64	  h_lsn;	/* lsn of this LR			:  8 */
 	__be64	  h_tail_lsn;	/* lsn of 1st LR w/ buffers not committed: 8 */
-	__be32	  h_chksum;	/* may not be used; non-zero if used	:  4 */
+	__be32	  h_crc;	/* crc of log record			:  4 */
 	__be32	  h_prev_block; /* block number to previous LR		:  4 */
 	__be32	  h_num_logops;	/* number of log operations in this LR	:  4 */
 	__be32	  h_cycle_data[XLOG_HEADER_CYCLE_SIZE / BBSIZE];
@@ -450,9 +450,11 @@ extern int	 xlog_find_tail(xlog_t	*log,
 				xfs_daddr_t *tail_blk);
 extern int	 xlog_recover(xlog_t *log);
 extern int	 xlog_recover_finish(xlog_t *log);
-extern void	 xlog_pack_data(xlog_t *log, xlog_in_core_t *iclog, int);
 extern void	 xlog_recover_process_iunlinks(xlog_t *log);
 
+extern __be32	 xlog_cksum(struct log *log, struct xlog_rec_header *rhead,
+			    char *dp, int size);
+
 extern struct xfs_buf *xlog_get_bp(xlog_t *, int);
 extern void	 xlog_put_bp(struct xfs_buf *);
 
Index: xfs/fs/xfs/xfs_log_recover.c
===================================================================
--- xfs.orig/fs/xfs/xfs_log_recover.c	2009-02-10 19:45:53.757070823 +0100
+++ xfs/fs/xfs/xfs_log_recover.c	2009-02-10 19:45:54.105069313 +0100
@@ -47,6 +47,7 @@
 #include "xfs_quota.h"
 #include "xfs_rw.h"
 #include "xfs_utils.h"
+#include "xfs_cksum.h"
 
 STATIC int	xlog_find_zeroed(xlog_t *, xfs_daddr_t *);
 STATIC int	xlog_clear_stale_blocks(xlog_t *, xfs_lsn_t);
@@ -3334,116 +3335,48 @@ xlog_recover_process_iunlinks(
 	mp->m_dmevmask = mp_dmevmask;
 }
 
-
-#ifdef DEBUG
-STATIC void
-xlog_pack_data_checksum(
-	xlog_t		*log,
-	xlog_in_core_t	*iclog,
-	int		size)
-{
-	int		i;
-	__be32		*up;
-	uint		chksum = 0;
-
-	up = (__be32 *)iclog->ic_datap;
-	/* divide length by 4 to get # words */
-	for (i = 0; i < (size >> 2); i++) {
-		chksum ^= be32_to_cpu(*up);
-		up++;
-	}
-	iclog->ic_header.h_chksum = cpu_to_be32(chksum);
-}
-#else
-#define xlog_pack_data_checksum(log, iclog, size)
-#endif
-
-/*
- * Stamp cycle number in every block
- */
-void
-xlog_pack_data(
-	xlog_t			*log,
-	xlog_in_core_t		*iclog,
-	int			roundoff)
-{
-	int			i, j, k;
-	int			size = iclog->ic_offset + roundoff;
-	__be32			cycle_lsn;
-	xfs_caddr_t		dp;
-
-	xlog_pack_data_checksum(log, iclog, size);
-
-	cycle_lsn = CYCLE_LSN_DISK(iclog->ic_header.h_lsn);
-
-	dp = iclog->ic_datap;
-	for (i = 0; i < BTOBB(size) &&
-		i < (XLOG_HEADER_CYCLE_SIZE / BBSIZE); i++) {
-		iclog->ic_header.h_cycle_data[i] = *(__be32 *)dp;
-		*(__be32 *)dp = cycle_lsn;
-		dp += BBSIZE;
-	}
-
-	if (xfs_sb_version_haslogv2(&log->l_mp->m_sb)) {
-		xlog_in_core_2_t *xhdr = iclog->ic_data;
-
-		for ( ; i < BTOBB(size); i++) {
-			j = i / (XLOG_HEADER_CYCLE_SIZE / BBSIZE);
-			k = i % (XLOG_HEADER_CYCLE_SIZE / BBSIZE);
-			xhdr[j].hic_xheader.xh_cycle_data[k] = *(__be32 *)dp;
-			*(__be32 *)dp = cycle_lsn;
-			dp += BBSIZE;
-		}
-
-		for (i = 1; i < log->l_iclog_heads; i++) {
-			xhdr[i].hic_xheader.xh_cycle = cycle_lsn;
-		}
-	}
-}
-
-#if defined(DEBUG) && defined(XFS_LOUD_RECOVERY)
-STATIC void
-xlog_unpack_data_checksum(
+STATIC int
+xlog_unpack_data_crc(
 	xlog_rec_header_t	*rhead,
 	xfs_caddr_t		dp,
 	xlog_t			*log)
 {
-	__be32			*up = (__be32 *)dp;
-	uint			chksum = 0;
-	int			i;
+	__be32			crc;
 
-	/* divide length by 4 to get # words */
-	for (i=0; i < be32_to_cpu(rhead->h_len) >> 2; i++) {
-		chksum ^= be32_to_cpu(*up);
-		up++;
-	}
-	if (chksum != be32_to_cpu(rhead->h_chksum)) {
-	    if (rhead->h_chksum ||
-		((log->l_flags & XLOG_CHKSUM_MISMATCH) == 0)) {
-		    cmn_err(CE_DEBUG,
-			"XFS: LogR chksum mismatch: was (0x%x) is (0x%x)\n",
-			    be32_to_cpu(rhead->h_chksum), chksum);
-		    cmn_err(CE_DEBUG,
-"XFS: Disregard message if filesystem was created with non-DEBUG kernel");
-		    if (xfs_sb_version_haslogv2(&log->l_mp->m_sb)) {
-			    cmn_err(CE_DEBUG,
-				"XFS: LogR this is a LogV2 filesystem\n");
-		    }
-		    log->l_flags |= XLOG_CHKSUM_MISMATCH;
-	    }
+	crc = xlog_cksum(log, rhead, dp, be32_to_cpu(rhead->h_len));
+	if (crc != rhead->h_crc) {
+		cmn_err(CE_ALERT, "XFS recovery: log record CRC error: "
+				"found 0x%x, expected 0x%x.\n",
+				be32_to_cpu(rhead->h_crc),
+				be32_to_cpu(crc));
+		print_hex_dump(KERN_ALERT, "record: ", 0, 32, 1, dp, 32, 0);
+
+		/*
+		 * If we've detected a log record corruption, then we
+		 * can't recover past this point. Abort recovery and
+		 * punt an error back up the stack.
+		 */
+		log->l_flags |= XLOG_CRC_MISMATCH;
+		return EUCLEAN;
 	}
+
+	return 0;
 }
-#else
-#define xlog_unpack_data_checksum(rhead, dp, log)
-#endif
 
-STATIC void
+STATIC int
 xlog_unpack_data(
 	xlog_rec_header_t	*rhead,
 	xfs_caddr_t		dp,
 	xlog_t			*log)
 {
 	int			i, j, k;
+	int			error;
+
+	if (xfs_sb_version_hascrc(&log->l_mp->m_sb)) {
+		error = xlog_unpack_data_crc(rhead, dp, log);
+		if (error)
+			return error;
+	}
 
 	for (i = 0; i < BTOBB(be32_to_cpu(rhead->h_len)) &&
 		  i < (XLOG_HEADER_CYCLE_SIZE / BBSIZE); i++) {
@@ -3461,7 +3394,7 @@ xlog_unpack_data(
 		}
 	}
 
-	xlog_unpack_data_checksum(rhead, dp, log);
+	return 0;
 }
 
 STATIC int
@@ -3593,9 +3526,13 @@ xlog_do_recovery_pass(
 			if (error)
 				goto bread_err2;
 
-			xlog_unpack_data(rhead, offset, log);
-			if ((error = xlog_recover_process_data(log,
-						rhash, rhead, offset, pass)))
+			error = xlog_unpack_data(rhead, offset, log);
+			if (error)
+				goto bread_err2;
+
+			error = xlog_recover_process_data(log,
+						rhash, rhead, offset, pass);
+			if (error)
 				goto bread_err2;
 			blk_no += bblks + hblks;
 		}
@@ -3734,9 +3671,14 @@ xlog_do_recovery_pass(
 					offset = xlog_align(log, wrapped_hblks,
 						bblks - split_bblks, dbp);
 			}
-			xlog_unpack_data(rhead, offset, log);
-			if ((error = xlog_recover_process_data(log, rhash,
-							rhead, offset, pass)))
+
+			error = xlog_unpack_data(rhead, offset, log);
+			if (error)
+				goto bread_err2;
+
+			error = xlog_recover_process_data(log, rhash,
+							rhead, offset, pass);
+			if (error)
 				goto bread_err2;
 			blk_no += bblks;
 		}
@@ -3761,9 +3703,13 @@ xlog_do_recovery_pass(
 			if (error)
 				goto bread_err2;
 
-			xlog_unpack_data(rhead, offset, log);
-			if ((error = xlog_recover_process_data(log, rhash,
-							rhead, offset, pass)))
+			error = xlog_unpack_data(rhead, offset, log);
+			if (error)
+				goto bread_err2;
+
+			error = xlog_recover_process_data(log, rhash,
+							rhead, offset, pass);
+			if (error)
 				goto bread_err2;
 			blk_no += bblks + hblks;
 		}
Index: xfs/fs/xfs/xfs_log.c
===================================================================
--- xfs.orig/fs/xfs/xfs_log.c	2009-02-10 19:21:28.338068613 +0100
+++ xfs/fs/xfs/xfs_log.c	2009-02-10 19:45:54.108070252 +0100
@@ -40,6 +40,7 @@
 #include "xfs_dinode.h"
 #include "xfs_inode.h"
 #include "xfs_rw.h"
+#include "xfs_cksum.h"
 
 kmem_zone_t	*xfs_log_ticket_zone;
 
@@ -1407,6 +1408,83 @@ xlog_grant_push_ail(xfs_mount_t	*mp,
 	    xfs_trans_ail_push(log->l_ailp, threshold_lsn);
 }	/* xlog_grant_push_ail */
 
+/*
+ * Stamp cycle number in every block
+ */
+STATIC void
+xlog_pack_data(
+	xlog_t			*log,
+	xlog_in_core_t		*iclog,
+	int			roundoff)
+{
+	int			i, j, k;
+	int			size = iclog->ic_offset + roundoff;
+	__be32			cycle_lsn;
+	xfs_caddr_t		dp;
+
+	cycle_lsn = CYCLE_LSN_DISK(iclog->ic_header.h_lsn);
+
+	dp = iclog->ic_datap;
+	for (i = 0; i < BTOBB(size); i++) {
+		if (i >= (XLOG_HEADER_CYCLE_SIZE / BBSIZE))
+			break;
+		iclog->ic_header.h_cycle_data[i] = *(__be32 *)dp;
+		*(__be32 *)dp = cycle_lsn;
+		dp += BBSIZE;
+	}
+
+	if (xfs_sb_version_haslogv2(&log->l_mp->m_sb)) {
+		xlog_in_core_2_t *xhdr = iclog->ic_data;
+
+		for ( ; i < BTOBB(size); i++) {
+			j = i / (XLOG_HEADER_CYCLE_SIZE / BBSIZE);
+			k = i % (XLOG_HEADER_CYCLE_SIZE / BBSIZE);
+			xhdr[j].hic_xheader.xh_cycle_data[k] = *(__be32 *)dp;
+			*(__be32 *)dp = cycle_lsn;
+			dp += BBSIZE;
+		}
+
+		for (i = 1; i < log->l_iclog_heads; i++)
+			xhdr[i].hic_xheader.xh_cycle = cycle_lsn;
+	}
+}
+
+/*
+ * Calculate the checksum for a log buffer.
+ *
+ * This is a little more complicated than it should be because the various
+ * headers and the actual data are non-contiguous.
+ */
+__be32
+xlog_cksum(
+	struct log		*log,
+	struct xlog_rec_header	*rhead,
+	char			*dp,
+	int			size)
+{
+	__uint32_t		crc;
+
+	/* first generate the crc for the record header ... */
+	crc = xfs_start_cksum((char *)rhead,
+			      sizeof(struct xlog_rec_header),
+			      offsetof(struct xlog_rec_header, h_crc));
+
+	/* ... then for additional cycle data for v2 logs ... */
+	if (xfs_sb_version_haslogv2(&log->l_mp->m_sb)) {
+		union xlog_in_core2 *xhdr = (union xlog_in_core2 *)rhead;
+		int		i;
+
+		for (i = 1; i < log->l_iclog_heads; i++) {
+			crc = crc32c(crc, &xhdr[i].hic_xheader,
+				     sizeof(struct xlog_rec_ext_header));
+		}
+	}
+
+	/* ... and finally for the payload */
+	crc = crc32c(crc, dp, size);
+
+	return xfs_end_cksum(crc);
+}
 
 /*
  * Flush out the in-core log (iclog) to the on-disk log in an asynchronous 
@@ -1437,7 +1515,6 @@ STATIC int
 xlog_sync(xlog_t		*log,
 	  xlog_in_core_t	*iclog)
 {
-	xfs_caddr_t	dptr;		/* pointer to byte sized element */
 	xfs_buf_t	*bp;
 	int		i;
 	uint		count;		/* byte count of bwrite */
@@ -1446,6 +1523,7 @@ xlog_sync(xlog_t		*log,
 	int		split = 0;	/* split write into two regions */
 	int		error;
 	int		v2 = xfs_sb_version_haslogv2(&log->l_mp->m_sb);
+	int		size;
 
 	XFS_STATS_INC(xs_log_writes);
 	ASSERT(atomic_read(&iclog->ic_refcnt) == 0);
@@ -1477,13 +1555,10 @@ xlog_sync(xlog_t		*log,
 	xlog_pack_data(log, iclog, roundoff); 
 
 	/* real byte length */
-	if (v2) {
-		iclog->ic_header.h_len =
-			cpu_to_be32(iclog->ic_offset + roundoff);
-	} else {
-		iclog->ic_header.h_len =
-			cpu_to_be32(iclog->ic_offset);
-	}
+	size = iclog->ic_offset;
+	if (v2)
+		size += roundoff;
+	iclog->ic_header.h_len = cpu_to_be32(size);
 
 	bp = iclog->ic_bp;
 	ASSERT(XFS_BUF_FSPRIVATE2(bp, unsigned long) == (unsigned long)1);
@@ -1494,12 +1569,39 @@ xlog_sync(xlog_t		*log,
 
 	/* Do we need to split this write into 2 parts? */
 	if (XFS_BUF_ADDR(bp) + BTOBB(count) > log->l_logBBsize) {
+		char		*dptr;
+
 		split = count - (BBTOB(log->l_logBBsize - XFS_BUF_ADDR(bp)));
 		count = BBTOB(log->l_logBBsize - XFS_BUF_ADDR(bp));
-		iclog->ic_bwritecnt = 2;	/* split into 2 writes */
+		iclog->ic_bwritecnt = 2;
+
+		/*
+		 * Bump the cycle numbers at the start of each block in the
+		 * part of the iclog that ends up in the buffer that gets
+		 * written to the start of the log.
+		 *
+		 * Watch out for the header magic number case, though.
+		 */
+		dptr = (char *)&iclog->ic_header + count;
+		for (i = 0; i < split; i += BBSIZE) {
+			__uint32_t cycle = be32_to_cpu(*(__be32 *)dptr);
+			if (++cycle == XLOG_HEADER_MAGIC_NUM)
+				cycle++;
+			*(__be32 *)dptr = cpu_to_be32(cycle);
+
+			dptr += BBSIZE;
+		}
 	} else {
 		iclog->ic_bwritecnt = 1;
 	}
+
+	/* calculcate the checksum */
+	if (xfs_sb_version_hascrc(&log->l_mp->m_sb)) {
+		iclog->ic_header.h_crc =
+			xlog_cksum(log, &iclog->ic_header,
+				   iclog->ic_datap, size);
+	}
+
 	XFS_BUF_SET_COUNT(bp, count);
 	XFS_BUF_SET_FSPRIVATE(bp, iclog);	/* save for later */
 	XFS_BUF_ZEROFLAGS(bp);
@@ -1536,27 +1638,13 @@ xlog_sync(xlog_t		*log,
 							(unsigned long)1);
 		XFS_BUF_SET_FSPRIVATE2(bp, (unsigned long)2);
 		XFS_BUF_SET_ADDR(bp, 0);	     /* logical 0 */
-		XFS_BUF_SET_PTR(bp, (xfs_caddr_t)((__psint_t)&(iclog->ic_header)+
-					    (__psint_t)count), split);
+		XFS_BUF_SET_PTR(bp, (char *)&iclog->ic_header + count, split);
 		XFS_BUF_SET_FSPRIVATE(bp, iclog);
 		XFS_BUF_ZEROFLAGS(bp);
 		XFS_BUF_BUSY(bp);
 		XFS_BUF_ASYNC(bp);
 		if (log->l_mp->m_flags & XFS_MOUNT_BARRIER)
 			XFS_BUF_ORDERED(bp);
-		dptr = XFS_BUF_PTR(bp);
-		/*
-		 * Bump the cycle numbers at the start of each block
-		 * since this part of the buffer is at the start of
-		 * a new cycle.  Watch out for the header magic number
-		 * case, though.
-		 */
-		for (i = 0; i < split; i += BBSIZE) {
-			be32_add_cpu((__be32 *)dptr, 1);
-			if (be32_to_cpu(*(__be32 *)dptr) == XLOG_HEADER_MAGIC_NUM)
-				be32_add_cpu((__be32 *)dptr, 1);
-			dptr += BBSIZE;
-		}
 
 		ASSERT(XFS_BUF_ADDR(bp) <= log->l_logBBsize-1);
 		ASSERT(XFS_BUF_ADDR(bp) + BTOBB(count) <= log->l_logBBsize);

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

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 12/13] xfs: add version 3 inode format with CRCs
  2009-02-10 20:22 [PATCH 00/13] Updated CRC patches Christoph Hellwig
                   ` (10 preceding siblings ...)
  2009-02-10 20:22 ` [PATCH 11/13] xfs: add CRC checks to the log Christoph Hellwig
@ 2009-02-10 20:22 ` Christoph Hellwig
  2009-02-12  6:38   ` Josef 'Jeff' Sipek
  2009-02-10 20:22 ` [PATCH 13/13] xfs: add CRC checks for quota blocks Christoph Hellwig
  12 siblings, 1 reply; 22+ messages in thread
From: Christoph Hellwig @ 2009-02-10 20:22 UTC (permalink / raw)
  To: xfs

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

Add a new inode version with a larger core.  The primary objective is
to allow for a crc of the inode, and location information (uuid and ino)
to verify it was written in the right place.  We also extend it by
a creation time (for Samba) and a changecount (for NFSv4) and some
additional padding.  These additional fields are not implemented yet,
but already layed out in the structure.


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

Index: xfs/fs/xfs/xfs_inode.h
===================================================================
--- xfs.orig/fs/xfs/xfs_inode.h	2009-02-10 19:45:50.921943721 +0100
+++ xfs/fs/xfs/xfs_inode.h	2009-02-10 19:45:59.186069347 +0100
@@ -152,6 +152,11 @@ typedef struct xfs_icdinode {
 	__uint32_t	di_gen;		/* generation number */
 } xfs_icdinode_t;
 
+static inline uint xfs_icdinode_size(struct xfs_icdinode *dicp)
+{
+	return sizeof(struct xfs_icdinode);
+}
+
 /*
  * Flags for xfs_ichgtime().
  */
Index: xfs/fs/xfs/xfs_inode_item.c
===================================================================
--- xfs.orig/fs/xfs/xfs_inode_item.c	2009-02-10 19:16:18.696943663 +0100
+++ xfs/fs/xfs/xfs_inode_item.c	2009-02-10 19:45:59.190098211 +0100
@@ -281,7 +281,7 @@ xfs_inode_item_format(
 	xfs_mark_inode_dirty_sync(ip);
 
 	vecp->i_addr = (xfs_caddr_t)&ip->i_d;
-	vecp->i_len  = sizeof(struct xfs_icdinode);
+	vecp->i_len  = xfs_icdinode_size(&ip->i_d);
 	XLOG_VEC_SET_TYPE(vecp, XLOG_REG_TYPE_ICORE);
 	vecp++;
 	nvecs++;
Index: xfs/fs/xfs/xfs_log_recover.c
===================================================================
--- xfs.orig/fs/xfs/xfs_log_recover.c	2009-02-10 19:45:54.105069313 +0100
+++ xfs/fs/xfs/xfs_log_recover.c	2009-02-10 19:46:08.354069897 +0100
@@ -2325,6 +2325,7 @@ xlog_recover_do_inode_trans(
 	int			attr_index;
 	uint			fields;
 	xfs_icdinode_t		*dicp;
+	uint			isize;
 	int			need_free = 0;
 
 	if (pass == XLOG_RECOVER_PASS1) {
@@ -2459,7 +2460,9 @@ xlog_recover_do_inode_trans(
 		error = EFSCORRUPTED;
 		goto error;
 	}
-	if (unlikely(item->ri_buf[1].i_len > sizeof(struct xfs_icdinode))) {
+
+	isize = xfs_icdinode_size(dicp);
+	if (unlikely(item->ri_buf[1].i_len > isize)) {
 		XFS_CORRUPTION_ERROR("xlog_recover_do_inode_trans(7)",
 				     XFS_ERRLEVEL_LOW, mp, dicp);
 		xfs_buf_relse(bp);
@@ -2471,13 +2474,13 @@ xlog_recover_do_inode_trans(
 	}
 
 	/* The core is in in-core format */
-	xfs_dinode_to_disk(dip, (xfs_icdinode_t *)item->ri_buf[1].i_addr);
+	xfs_dinode_to_disk(dip, dicp);
 
 	/* the rest is in on-disk format */
-	if (item->ri_buf[1].i_len > sizeof(struct xfs_icdinode)) {
-		memcpy((xfs_caddr_t) dip + sizeof(struct xfs_icdinode),
-			item->ri_buf[1].i_addr + sizeof(struct xfs_icdinode),
-			item->ri_buf[1].i_len  - sizeof(struct xfs_icdinode));
+	if (item->ri_buf[1].i_len > isize) {
+		memcpy((xfs_caddr_t) dip + isize,
+			item->ri_buf[1].i_addr + isize,
+			item->ri_buf[1].i_len  - isize);
 	}
 
 	fields = in_f->ilf_fields;
@@ -2561,6 +2564,15 @@ xlog_recover_do_inode_trans(
 	}
 
 write_inode_buffer:
+	/* re-generate the checksum. */
+	if (dip->di_version == 3) {
+		__uint32_t	crc;
+
+		crc = xfs_start_cksum((char *)dip, mp->m_sb.sb_inodesize,
+				      offsetof(struct xfs_dinode, di_crc));
+		dip->di_crc = xfs_end_cksum(crc);
+	}
+
 	if (ITEM_TYPE(item) == XFS_LI_INODE) {
 		ASSERT(bp->b_mount == NULL || bp->b_mount == mp);
 		bp->b_mount = mp;
Index: xfs/fs/xfs/xfs_dinode.h
===================================================================
--- xfs.orig/fs/xfs/xfs_dinode.h	2009-02-10 19:45:51.939069576 +0100
+++ xfs/fs/xfs/xfs_dinode.h	2009-02-10 19:45:59.195068745 +0100
@@ -19,7 +19,7 @@
 #define	__XFS_DINODE_H__
 
 #define	XFS_DINODE_MAGIC		0x494e	/* 'IN' */
-#define XFS_DINODE_GOOD_VERSION(v)	(((v) == 1 || (v) == 2))
+#define XFS_DINODE_GOOD_VERSION(v)	((v) >= 1 && (v) <= 3)
 
 typedef struct xfs_timestamp {
 	__be32		t_sec;		/* timestamp seconds */
@@ -69,11 +69,32 @@ typedef struct xfs_dinode {
 
 	/* di_next_unlinked is the only non-core field in the old dinode */
 	__be32		di_next_unlinked;/* agi unlinked list ptr */
-} __attribute__((packed)) xfs_dinode_t;
+
+	/* start of the extended dinode, writable fields */
+	__be32		di_crc;		/* CRC of the inode */
+	__be64		di_changecount;	/* number of attribute changes */
+	__u8		di_pad2[16];	/* more padding for future expansion */
+
+	/* fields only written to during inode creation */
+	xfs_timestamp_t	di_crtime;	/* time created */
+	__be64		di_ino;		/* inode number */
+	uuid_t		di_uuid;	/* UUID of the filesystem */
+} xfs_dinode_t;
 
 #define DI_MAX_FLUSH 0xffff
 
 /*
+ * Size of the core inode on disk.  Version 1 and 2 inodes have
+ * the same size, but version 3 has grown a few additional fields.
+ */
+static inline uint xfs_dinode_size(int version)
+{
+	if (version == 3)
+		return sizeof(struct xfs_dinode);
+	return offsetof(struct xfs_dinode, di_crc);
+}
+
+/*
  * The 32 bit link count in the inode theoretically maxes out at UINT_MAX.
  * Since the pathconf interface is signed, we use 2^31 - 1 instead.
  * The old inode format had a 16 bit link count, so its maximum is USHRT_MAX.
@@ -104,7 +125,7 @@ typedef enum xfs_dinode_fmt {
  * Inode size for given fs.
  */
 #define XFS_LITINO(version, mp) \
-	((int)(((mp)->m_sb.sb_inodesize) - sizeof(struct xfs_dinode)))
+	((int)(((mp)->m_sb.sb_inodesize) - xfs_dinode_size(version)))
 
 #define XFS_BROOT_SIZE_ADJ(ip) \
 	(XFS_BMBT_BLOCK_LEN((ip)->i_mount) - sizeof(xfs_bmdr_block_t))
@@ -132,7 +153,7 @@ typedef enum xfs_dinode_fmt {
  * Return pointers to the data or attribute forks.
  */
 #define XFS_DFORK_DPTR(dip) \
-	((char *)(dip) + sizeof(struct xfs_dinode))
+	((char *)dip + xfs_dinode_size(dip->di_version))
 #define XFS_DFORK_APTR(dip)	\
 	(XFS_DFORK_DPTR(dip) + XFS_DFORK_BOFF(dip))
 #define XFS_DFORK_PTR(dip,w)	\
Index: xfs/fs/xfs/xfs_ialloc.c
===================================================================
--- xfs.orig/fs/xfs/xfs_ialloc.c	2009-02-10 19:45:53.408069901 +0100
+++ xfs/fs/xfs/xfs_ialloc.c	2009-02-10 19:46:08.351069375 +0100
@@ -163,6 +163,7 @@ xfs_ialloc_ag_alloc(
 	xfs_buf_t	*agbp,		/* alloc group buffer */
 	int		*alloc)
 {
+	xfs_mount_t	*mp = tp->t_mountp;
 	xfs_agi_t	*agi;		/* allocation group header */
 	xfs_alloc_arg_t	args;		/* allocation argument structure */
 	int		blks_per_cluster;  /* fs blocks per inode cluster */
@@ -191,11 +192,10 @@ xfs_ialloc_ag_alloc(
 	 * Locking will ensure that we don't have two callers in here
 	 * at one time.
 	 */
-	newlen = XFS_IALLOC_INODES(args.mp);
-	if (args.mp->m_maxicount &&
-	    args.mp->m_sb.sb_icount + newlen > args.mp->m_maxicount)
+	newlen = XFS_IALLOC_INODES(mp);
+	if (mp->m_maxicount && mp->m_sb.sb_icount + newlen > mp->m_maxicount)
 		return XFS_ERROR(ENOSPC);
-	args.minlen = args.maxlen = XFS_IALLOC_BLOCKS(args.mp);
+	args.minlen = args.maxlen = XFS_IALLOC_BLOCKS(mp);
 	/*
 	 * First try to allocate inodes contiguous with the last-allocated
 	 * chunk of inodes.  If the filesystem is striped, this will fill
@@ -203,12 +203,13 @@ xfs_ialloc_ag_alloc(
  	 */
 	agi = XFS_BUF_TO_AGI(agbp);
 	newino = be32_to_cpu(agi->agi_newino);
-	args.agbno = XFS_AGINO_TO_AGBNO(args.mp, newino) +
-			XFS_IALLOC_BLOCKS(args.mp);
+	agno = be32_to_cpu(agi->agi_seqno);
+
+	args.agbno = XFS_AGINO_TO_AGBNO(mp, newino) + XFS_IALLOC_BLOCKS(mp);
+
 	if (likely(newino != NULLAGINO &&
 		  (args.agbno < be32_to_cpu(agi->agi_length)))) {
-		args.fsbno = XFS_AGB_TO_FSB(args.mp,
-				be32_to_cpu(agi->agi_seqno), args.agbno);
+		args.fsbno = XFS_AGB_TO_FSB(mp, agno, args.agbno);
 		args.type = XFS_ALLOCTYPE_THIS_BNO;
 		args.mod = args.total = args.wasdel = args.isfl =
 			args.userdata = args.minalignslop = 0;
@@ -231,7 +232,7 @@ xfs_ialloc_ag_alloc(
 		args.minalignslop = xfs_ialloc_cluster_alignment(&args) - 1;
 
 		/* Allow space for the inode btree to split. */
-		args.minleft = args.mp->m_in_maxlevels - 1;
+		args.minleft = mp->m_in_maxlevels - 1;
 		if ((error = xfs_alloc_vextent(&args)))
 			return error;
 	} else
@@ -247,9 +248,9 @@ xfs_ialloc_ag_alloc(
 		 * pieces, so don't need alignment anyway.
 		 */
 		isaligned = 0;
-		if (args.mp->m_sinoalign) {
-			ASSERT(!(args.mp->m_flags & XFS_MOUNT_NOALIGN));
-			args.alignment = args.mp->m_dalign;
+		if (mp->m_sinoalign) {
+			ASSERT(!(mp->m_flags & XFS_MOUNT_NOALIGN));
+			args.alignment = mp->m_dalign;
 			isaligned = 1;
 		} else
 			args.alignment = xfs_ialloc_cluster_alignment(&args);
@@ -259,8 +260,7 @@ xfs_ialloc_ag_alloc(
 		 * For now, just allocate blocks up front.
 		 */
 		args.agbno = be32_to_cpu(agi->agi_root);
-		args.fsbno = XFS_AGB_TO_FSB(args.mp,
-				be32_to_cpu(agi->agi_seqno), args.agbno);
+		args.fsbno = XFS_AGB_TO_FSB(mp, agno, args.agbno);
 		/*
 		 * Allocate a fixed-size extent of inodes.
 		 */
@@ -271,7 +271,7 @@ xfs_ialloc_ag_alloc(
 		/*
 		 * Allow space for the inode btree to split.
 		 */
-		args.minleft = args.mp->m_in_maxlevels - 1;
+		args.minleft = mp->m_in_maxlevels - 1;
 		if ((error = xfs_alloc_vextent(&args)))
 			return error;
 	}
@@ -283,8 +283,7 @@ xfs_ialloc_ag_alloc(
 	if (isaligned && args.fsbno == NULLFSBLOCK) {
 		args.type = XFS_ALLOCTYPE_NEAR_BNO;
 		args.agbno = be32_to_cpu(agi->agi_root);
-		args.fsbno = XFS_AGB_TO_FSB(args.mp,
-				be32_to_cpu(agi->agi_seqno), args.agbno);
+		args.fsbno = XFS_AGB_TO_FSB(mp, agno, args.agbno);
 		args.alignment = xfs_ialloc_cluster_alignment(&args);
 		if ((error = xfs_alloc_vextent(&args)))
 			return error;
@@ -298,21 +297,21 @@ xfs_ialloc_ag_alloc(
 	/*
 	 * Convert the results.
 	 */
-	newino = XFS_OFFBNO_TO_AGINO(args.mp, args.agbno, 0);
+	newino = XFS_OFFBNO_TO_AGINO(mp, args.agbno, 0);
 	/*
 	 * Loop over the new block(s), filling in the inodes.
 	 * For small block sizes, manipulate the inodes in buffers
 	 * which are multiples of the blocks size.
 	 */
-	if (args.mp->m_sb.sb_blocksize >= XFS_INODE_CLUSTER_SIZE(args.mp)) {
+	if (mp->m_sb.sb_blocksize >= XFS_INODE_CLUSTER_SIZE(mp)) {
 		blks_per_cluster = 1;
 		nbufs = (int)args.len;
-		ninodes = args.mp->m_sb.sb_inopblock;
+		ninodes = mp->m_sb.sb_inopblock;
 	} else {
-		blks_per_cluster = XFS_INODE_CLUSTER_SIZE(args.mp) /
-				   args.mp->m_sb.sb_blocksize;
+		blks_per_cluster = XFS_INODE_CLUSTER_SIZE(mp) /
+				   mp->m_sb.sb_blocksize;
 		nbufs = (int)args.len / blks_per_cluster;
-		ninodes = blks_per_cluster * args.mp->m_sb.sb_inopblock;
+		ninodes = blks_per_cluster * mp->m_sb.sb_inopblock;
 	}
 	/*
 	 * Figure out what version number to use in the inodes we create.
@@ -321,7 +320,9 @@ xfs_ialloc_ag_alloc(
 	 * use the old version so that old kernels will continue to be
 	 * able to use the file system.
 	 */
-	if (xfs_sb_version_hasnlink(&args.mp->m_sb))
+	if (xfs_sb_version_hascrc(&mp->m_sb))
+		version = 3;
+	else if (xfs_sb_version_hasnlink(&mp->m_sb))
 		version = 2;
 	else
 		version = 1;
@@ -335,13 +336,15 @@ xfs_ialloc_ag_alloc(
 	 */
 	gen = random32();
 	for (j = 0; j < nbufs; j++) {
+		xfs_agblock_t agbno;
+
 		/*
 		 * Get the block.
 		 */
-		d = XFS_AGB_TO_DADDR(args.mp, be32_to_cpu(agi->agi_seqno),
-				     args.agbno + (j * blks_per_cluster));
-		fbuf = xfs_trans_get_buf(tp, args.mp->m_ddev_targp, d,
-					 args.mp->m_bsize * blks_per_cluster,
+		agbno = args.agbno + (j * blks_per_cluster);
+		d = XFS_AGB_TO_DADDR(mp, agno, agbno);
+		fbuf = xfs_trans_get_buf(tp, mp->m_ddev_targp, d,
+					 mp->m_bsize * blks_per_cluster,
 					 XFS_BUF_LOCK);
 		ASSERT(fbuf);
 		ASSERT(!XFS_BUF_GETERROR(fbuf));
@@ -353,31 +356,44 @@ xfs_ialloc_ag_alloc(
 		 *      log a whole cluster of inodes instead of all the indivdual
 		 *      transactions causing a lot of log traffic.
 		 */
-		xfs_biozero(fbuf, 0, ninodes << args.mp->m_sb.sb_inodelog);
+		xfs_biozero(fbuf, 0, ninodes << mp->m_sb.sb_inodelog);
 		for (i = 0; i < ninodes; i++) {
-			int	ioffset = i << args.mp->m_sb.sb_inodelog;
-			uint	isize = sizeof(struct xfs_dinode);
+			int	ioffset = i << mp->m_sb.sb_inodelog;
+			uint	isize = xfs_dinode_size(version);
 
-			free = xfs_make_iptr(args.mp, fbuf, i);
+			free = xfs_make_iptr(mp, fbuf, i);
 			free->di_magic = cpu_to_be16(XFS_DINODE_MAGIC);
 			free->di_version = version;
 			free->di_gen = cpu_to_be32(gen);
 			free->di_next_unlinked = cpu_to_be32(NULLAGINO);
+
+			if (version == 3) {
+				__uint32_t	crc;
+
+				free->di_ino = cpu_to_be64(
+					XFS_AGINO_TO_INO(mp, agno,
+						XFS_OFFBNO_TO_AGINO(mp, agbno, i)));
+				uuid_copy(&free->di_uuid, &mp->m_sb.sb_uuid);
+
+				crc = xfs_start_cksum((char *)free,
+					mp->m_sb.sb_inodesize,
+					offsetof(struct xfs_dinode, di_crc));
+				free->di_crc = xfs_end_cksum(crc);
+			}
 			xfs_trans_log_buf(tp, fbuf, ioffset, ioffset + isize - 1);
 		}
 		xfs_trans_inode_alloc_buf(tp, fbuf);
 	}
 	be32_add_cpu(&agi->agi_count, newlen);
 	be32_add_cpu(&agi->agi_freecount, newlen);
-	agno = be32_to_cpu(agi->agi_seqno);
-	down_read(&args.mp->m_peraglock);
-	args.mp->m_perag[agno].pagi_freecount += newlen;
-	up_read(&args.mp->m_peraglock);
+	down_read(&mp->m_peraglock);
+	mp->m_perag[agno].pagi_freecount += newlen;
+	up_read(&mp->m_peraglock);
 	agi->agi_newino = cpu_to_be32(newino);
 	/*
 	 * Insert records describing the new inode chunk into the btree.
 	 */
-	cur = xfs_inobt_init_cursor(args.mp, tp, agbp, agno);
+	cur = xfs_inobt_init_cursor(mp, tp, agbp, agno);
 	for (thisino = newino;
 	     thisino < newino + newlen;
 	     thisino += XFS_INODES_PER_CHUNK) {
Index: xfs/fs/xfs/xfs_inode.c
===================================================================
--- xfs.orig/fs/xfs/xfs_inode.c	2009-02-10 19:46:02.110944088 +0100
+++ xfs/fs/xfs/xfs_inode.c	2009-02-10 19:46:08.309069135 +0100
@@ -52,6 +52,7 @@
 #include "xfs_acl.h"
 #include "xfs_filestream.h"
 #include "xfs_vnodeops.h"
+#include "xfs_cksum.h"
 
 kmem_zone_t *xfs_ifork_zone;
 kmem_zone_t *xfs_inode_zone;
@@ -827,6 +828,23 @@ xfs_iread(
 	 * Otherwise, just get the truly permanent information.
 	 */
 	if (dip->di_mode) {
+		/* validate the checksum. */
+		if (dip->di_version == 3) {
+			if (!xfs_verify_cksum((char *)dip, mp->m_sb.sb_inodesize,
+					      offsetof(struct xfs_dinode, di_crc)) ||
+		    	    !uuid_equal(&dip->di_uuid, &mp->m_sb.sb_uuid) ||
+			    be64_to_cpu(dip->di_ino) != ip->i_ino) {
+				xfs_fs_cmn_err(CE_ALERT, mp,
+	"xfs_iread: checksum validation failed for inode %lld", ip->i_ino);
+
+				XFS_CORRUPTION_ERROR("xfs_iread crc",
+						     XFS_ERRLEVEL_LOW,
+						     mp, dip);
+				error = XFS_ERROR(EFSCORRUPTED);
+				goto out_brelse;
+			}
+		}
+
 		xfs_dinode_from_disk(&ip->i_d, dip);
 		error = xfs_iformat(ip, dip);
 		if (error)  {
@@ -3171,6 +3189,15 @@ xfs_iflush_int(
 		xfs_iflush_fork(ip, dip, iip, XFS_ATTR_FORK, bp);
 	xfs_inobp_check(mp, bp);
 
+	/* generate the checksum. */
+	if (dip->di_version == 3) {
+		__uint32_t	crc;
+
+		crc = xfs_start_cksum((char *)dip, mp->m_sb.sb_inodesize,
+				      offsetof(struct xfs_dinode, di_crc));
+		dip->di_crc = xfs_end_cksum(crc);
+	}
+
 	/*
 	 * We've recorded everything logged in the inode, so we'd
 	 * like to clear the ilf_fields bits so we don't log and

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

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 13/13] xfs: add CRC checks for quota blocks
  2009-02-10 20:22 [PATCH 00/13] Updated CRC patches Christoph Hellwig
                   ` (11 preceding siblings ...)
  2009-02-10 20:22 ` [PATCH 12/13] xfs: add version 3 inode format with CRCs Christoph Hellwig
@ 2009-02-10 20:22 ` Christoph Hellwig
  2009-02-12  6:41   ` Josef 'Jeff' Sipek
  12 siblings, 1 reply; 22+ messages in thread
From: Christoph Hellwig @ 2009-02-10 20:22 UTC (permalink / raw)
  To: xfs

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

Use the reserved space in struct xfs_dqblk to store a UUID and a crc
for the quota blocks.

I'm pondering if we should just move the crc check into xfs_qm_dqcheck
where all the other validity checks are located.


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

Index: xfs/fs/xfs/xfs_quota.h
===================================================================
--- xfs.orig/fs/xfs/xfs_quota.h	2009-02-09 08:47:34.234069111 +0100
+++ xfs/fs/xfs/xfs_quota.h	2009-02-10 20:15:36.874947481 +0100
@@ -77,7 +77,13 @@ typedef struct	xfs_disk_dquot {
  */
 typedef struct xfs_dqblk {
 	xfs_disk_dquot_t  dd_diskdq;	/* portion that lives incore as well */
-	char		  dd_fill[32];	/* filling for posterity */
+	char		  dd_fill[12];	/* filling for posterity */
+
+	/*
+	 * These two are only present one filesystems with the CRC bits set.
+	 */
+	__be32		  dd_crc;	/* checksum */
+	uuid_t		  dd_uuid;	/* location information */
 } xfs_dqblk_t;
 
 /*
Index: xfs/fs/xfs/quota/xfs_dquot.c
===================================================================
--- xfs.orig/fs/xfs/quota/xfs_dquot.c	2009-02-10 19:55:01.982070089 +0100
+++ xfs/fs/xfs/quota/xfs_dquot.c	2009-02-10 20:23:25.618944664 +0100
@@ -48,6 +48,7 @@
 #include "xfs_trans_space.h"
 #include "xfs_trans_priv.h"
 #include "xfs_qm.h"
+#include "xfs_cksum.h"
 
 
 /*
@@ -368,6 +369,40 @@ xfs_qm_adjust_dqtimers(
 	}
 }
 
+STATIC void
+xfs_dquot_calc_crc(
+	struct xfs_buf		*bp)
+{
+	struct xfs_dqblk	*d = (struct xfs_dqblk *)XFS_BUF_PTR(bp);
+	int			i;
+
+	for (i = 0; i < XFS_QM_DQPERBLK(bp->b_mount); i++, d++) {
+		xfs_update_cksum((char *)d, sizeof(struct xfs_dqblk),
+				 offsetof(struct xfs_dqblk, dd_crc));
+	}
+}
+
+STATIC int
+xfs_dquot_verify_crc(
+	struct xfs_mount	*mp,
+	struct xfs_buf		*bp)
+{
+	struct xfs_dqblk	*d = (struct xfs_dqblk *)XFS_BUF_PTR(bp);
+	int			i;
+
+	for (i = 0; i < XFS_QM_DQPERBLK(mp); i++, d++) {
+		if (!xfs_verify_cksum((char *)d, sizeof(struct xfs_dqblk),
+				 offsetof(struct xfs_dqblk, dd_crc))) {
+//		    !uuid_equal(&agfl->agfl_uuid, &mp->m_sb.sb_uuid) ||
+			XFS_CORRUPTION_ERROR("xfs_qm_dqtobp crc",
+					XFS_ERRLEVEL_LOW, mp, d);
+			return XFS_ERROR(EFSCORRUPTED);
+		}
+	}
+
+	return 0;
+}
+
 /*
  * initialize a buffer full of dquots and log the whole thing
  */
@@ -476,6 +511,10 @@ xfs_qm_dqalloc(
 			       0);
 	if (!bp || (error = XFS_BUF_GETERROR(bp)))
 		goto error1;
+
+	if (xfs_sb_version_hascrc(&mp->m_sb))
+		xfs_buf_set_io_callback(bp, xfs_dquot_calc_crc);
+
 	/*
 	 * Make a chunk of dquots out of this buffer and log
 	 * the entire thing.
@@ -539,6 +578,7 @@ xfs_qm_dqtobp(
 	xfs_inode_t	*quotip;
 	xfs_mount_t	*mp;
 	xfs_disk_dquot_t *ddq;
+	struct xfs_dqblk *d;
 	xfs_dqid_t	id;
 	boolean_t	newdquot;
 	xfs_trans_t	*tp = (tpp ? *tpp : NULL);
@@ -622,6 +662,22 @@ xfs_qm_dqtobp(
 		}
 		if (error || !bp)
 			return XFS_ERROR(error);
+
+		/*
+		 * Validate the CRC of the AGF block only if the block is clean (i.e.
+		 * it just came from disk).
+		 */
+		if (xfs_sb_version_hascrc(&mp->m_sb) &&
+		    !(XFS_BUF_ISWRITE(bp) || XFS_BUF_ISDELAYWRITE(bp))) {
+			error = xfs_dquot_verify_crc(mp, bp);
+			if (error) {
+				xfs_trans_brelse(tp, bp);
+				return error;
+			}
+
+			xfs_buf_set_io_callback(bp, xfs_dquot_calc_crc);
+		}
+
 	}
 	ASSERT(XFS_BUF_ISBUSY(bp));
 	ASSERT(XFS_BUF_VALUSEMA(bp) <= 0);
@@ -629,7 +685,8 @@ xfs_qm_dqtobp(
 	/*
 	 * calculate the location of the dquot inside the buffer.
 	 */
-	ddq = (xfs_disk_dquot_t *)((char *)XFS_BUF_PTR(bp) + dqp->q_bufoffset);
+	d = (struct xfs_dqblk *)(XFS_BUF_PTR(bp) + dqp->q_bufoffset);
+	ddq = &d->dd_diskdq;
 
 	/*
 	 * A simple sanity check in case we got a corrupted dquot...
Index: xfs/fs/xfs/quota/xfs_qm.c
===================================================================
--- xfs.orig/fs/xfs/quota/xfs_qm.c	2009-02-10 19:55:02.006069507 +0100
+++ xfs/fs/xfs/quota/xfs_qm.c	2009-02-10 19:58:48.005974236 +0100
@@ -1430,6 +1430,10 @@ xfs_qm_dqiter_bufs(
 		if (error)
 			break;
 
+		/*
+		 * XXX(hch): need to figure out if it makes sense to validate
+		 *	     the CRC here.
+		 */
 		xfs_qm_reset_dqcounts(mp, bp, firstid, type);
 		xfs_bdwrite(mp, bp);
 		/*

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

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 10/13] xfs: add CRC checks to the AGFL
  2009-02-10 20:22 ` [PATCH 10/13] xfs: add CRC checks to the AGFL Christoph Hellwig
@ 2009-02-11  7:54   ` Dave Chinner
  2009-02-15 18:23     ` Christoph Hellwig
  0 siblings, 1 reply; 22+ messages in thread
From: Dave Chinner @ 2009-02-11  7:54 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: xfs

On Tue, Feb 10, 2009 at 03:22:51PM -0500, Christoph Hellwig wrote:
> 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.

I haven't had a chance to look over any of this series in detail - just
a quick glance really - but this popped out as looking wrong:

> +/*
> + * 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))

sb_sectsize is in bytes, sizeof(xfs_agblock_t) is in bytes, which
means that the numerator is a count of the number of agblocks that
will fit in the AGFL. sizeof(struct xfs_agfl) is also in bytes,
so your subtracting a number of bytes from a count of agblocks....

I think you mean:

#define XFS_AGFL_SIZE(mp) \
	(((mp)->m_sb.sb_sectsize - (xfs_sb_version_hascrc(&((mp)->m_sb)) ? \
						sizeof(struct xfs_agfl) : 0)) \
	  / sizeof(xfs_agblock_t))

>  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;

And judging by that you are stealing more than 2 slots - more like
8 slots.

Cheers,

Dave.
-- 
Dave Chinner
david@fromorbit.com

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

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 05/13] xfs: add CRC infrastructure
  2009-02-10 20:22 ` [PATCH 05/13] xfs: add CRC infrastructure Christoph Hellwig
@ 2009-02-12  6:10   ` Josef 'Jeff' Sipek
  0 siblings, 0 replies; 22+ messages in thread
From: Josef 'Jeff' Sipek @ 2009-02-12  6:10 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: xfs

On Tue, Feb 10, 2009 at 03:22:46PM -0500, Christoph Hellwig wrote:
...
> Index: xfs/fs/xfs/xfs_cksum.h
> ===================================================================
> --- /dev/null	1970-01-01 00:00:00.000000000 +0000
> +++ xfs/fs/xfs/xfs_cksum.h	2009-02-05 19:04:31.282972630 +0100
> @@ -0,0 +1,62 @@
> +#ifndef _XFS_CKSUM_H
> +#define _XFS_CKSUM_H 1
> +
> +#define XFS_CRC_SEED	(~(__uint32_t)0)

Is this the final seed you want to use, or was this just a
work-in-progress-non-zero value for testing?

...
> +/*
> + * Convert the intermediate checksum to the final ondisk format.
> + *
> + * Note that crc32c is already endianess agnostic, so no additional
> + * byte swap is needed.
> + */
> +static inline __be32
> +xfs_end_cksum(__uint32_t crc)
> +{
> +	return (__force __be32)~crc;
> +}

Why the bit-wise not?

Josef 'Jeff' Sipek.

-- 
Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are, by
definition, not smart enough to debug it.
		- Brian W. Kernighan 

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

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 12/13] xfs: add version 3 inode format with CRCs
  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
  0 siblings, 1 reply; 22+ messages in thread
From: Josef 'Jeff' Sipek @ 2009-02-12  6:38 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: xfs

On Tue, Feb 10, 2009 at 03:22:53PM -0500, Christoph Hellwig wrote:
...
> Index: xfs/fs/xfs/xfs_dinode.h
> ===================================================================
> --- xfs.orig/fs/xfs/xfs_dinode.h	2009-02-10 19:45:51.939069576 +0100
> +++ xfs/fs/xfs/xfs_dinode.h	2009-02-10 19:45:59.195068745 +0100
> @@ -69,11 +69,32 @@ typedef struct xfs_dinode {
>  
>  	/* di_next_unlinked is the only non-core field in the old dinode */
>  	__be32		di_next_unlinked;/* agi unlinked list ptr */
> -} __attribute__((packed)) xfs_dinode_t;
> +
> +	/* start of the extended dinode, writable fields */
> +	__be32		di_crc;		/* CRC of the inode */
> +	__be64		di_changecount;	/* number of attribute changes */
> +	__u8		di_pad2[16];	/* more padding for future expansion */
> +
> +	/* fields only written to during inode creation */
> +	xfs_timestamp_t	di_crtime;	/* time created */
> +	__be64		di_ino;		/* inode number */
> +	uuid_t		di_uuid;	/* UUID of the filesystem */
> +} xfs_dinode_t;

Hrm...removing the packed attribute... Eric, do you remember the ARM ABI
alignment rules? Regardless of ARM, are those fields aligned nicely? (From a
quick glance at the code looks ok.)

Also, why is the padding filed in the middle of these fields? IOW, why are
crtime/ino/uuid at the end?

Josef 'Jeff' Sipek.

-- 
Bad pun of the week: The formula 1 control computer suffered from a race
condition

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

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 13/13] xfs: add CRC checks for quota blocks
  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
  0 siblings, 1 reply; 22+ messages in thread
From: Josef 'Jeff' Sipek @ 2009-02-12  6:41 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: xfs

On Tue, Feb 10, 2009 at 03:22:54PM -0500, Christoph Hellwig wrote:
> Use the reserved space in struct xfs_dqblk to store a UUID and a crc
> for the quota blocks.
> 
> I'm pondering if we should just move the crc check into xfs_qm_dqcheck
> where all the other validity checks are located.
> 
> 
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> 
> Index: xfs/fs/xfs/xfs_quota.h
> ===================================================================
> --- xfs.orig/fs/xfs/xfs_quota.h	2009-02-09 08:47:34.234069111 +0100
> +++ xfs/fs/xfs/xfs_quota.h	2009-02-10 20:15:36.874947481 +0100
> @@ -77,7 +77,13 @@ typedef struct	xfs_disk_dquot {
>   */
>  typedef struct xfs_dqblk {
>  	xfs_disk_dquot_t  dd_diskdq;	/* portion that lives incore as well */
> -	char		  dd_fill[32];	/* filling for posterity */
> +	char		  dd_fill[12];	/* filling for posterity */
> +
> +	/*
> +	 * These two are only present one filesystems with the CRC bits set.
> +	 */
> +	__be32		  dd_crc;	/* checksum */
> +	uuid_t		  dd_uuid;	/* location information */
>  } xfs_dqblk_t;

Again, why put the crc/uuid at the end?

> Index: xfs/fs/xfs/quota/xfs_dquot.c
> ===================================================================
> --- xfs.orig/fs/xfs/quota/xfs_dquot.c	2009-02-10 19:55:01.982070089 +0100
> +++ xfs/fs/xfs/quota/xfs_dquot.c	2009-02-10 20:23:25.618944664 +0100
> @@ -368,6 +369,40 @@ xfs_qm_adjust_dqtimers(
...
> +STATIC int
> +xfs_dquot_verify_crc(
> +	struct xfs_mount	*mp,
> +	struct xfs_buf		*bp)
> +{
> +	struct xfs_dqblk	*d = (struct xfs_dqblk *)XFS_BUF_PTR(bp);
> +	int			i;
> +
> +	for (i = 0; i < XFS_QM_DQPERBLK(mp); i++, d++) {
> +		if (!xfs_verify_cksum((char *)d, sizeof(struct xfs_dqblk),
> +				 offsetof(struct xfs_dqblk, dd_crc))) {
> +//		    !uuid_equal(&agfl->agfl_uuid, &mp->m_sb.sb_uuid) ||

Dead code?

Josef 'Jeff' Sipek.

-- 
FORTUNE PROVIDES QUESTIONS FOR THE GREAT ANSWERS: #19
A:      To be or not to be.
Q:      What is the square root of 4b^2?

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

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 12/13] xfs: add version 3 inode format with CRCs
  2009-02-12  6:38   ` Josef 'Jeff' Sipek
@ 2009-02-12 18:42     ` Eric Sandeen
  2009-02-12 18:51       ` Christoph Hellwig
  0 siblings, 1 reply; 22+ messages in thread
From: Eric Sandeen @ 2009-02-12 18:42 UTC (permalink / raw)
  To: Josef 'Jeff' Sipek; +Cc: Christoph Hellwig, xfs

Josef 'Jeff' Sipek wrote:
> On Tue, Feb 10, 2009 at 03:22:53PM -0500, Christoph Hellwig wrote:
> ...
>> Index: xfs/fs/xfs/xfs_dinode.h
>> ===================================================================
>> --- xfs.orig/fs/xfs/xfs_dinode.h	2009-02-10 19:45:51.939069576 +0100
>> +++ xfs/fs/xfs/xfs_dinode.h	2009-02-10 19:45:59.195068745 +0100
>> @@ -69,11 +69,32 @@ typedef struct xfs_dinode {
>>  
>>  	/* di_next_unlinked is the only non-core field in the old dinode */
>>  	__be32		di_next_unlinked;/* agi unlinked list ptr */
>> -} __attribute__((packed)) xfs_dinode_t;
>> +
>> +	/* start of the extended dinode, writable fields */
>> +	__be32		di_crc;		/* CRC of the inode */
>> +	__be64		di_changecount;	/* number of attribute changes */
>> +	__u8		di_pad2[16];	/* more padding for future expansion */
>> +
>> +	/* fields only written to during inode creation */
>> +	xfs_timestamp_t	di_crtime;	/* time created */
>> +	__be64		di_ino;		/* inode number */
>> +	uuid_t		di_uuid;	/* UUID of the filesystem */
>> +} xfs_dinode_t;
> 
> Hrm...removing the packed attribute... Eric, do you remember the ARM ABI
> alignment rules? Regardless of ARM, are those fields aligned nicely? (From a
> quick glance at the code looks ok.)

I'll just have to just test it again I suppose.  Removing packed is
good, as long as the padding makes it all come out right.

-=Eric

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

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 12/13] xfs: add version 3 inode format with CRCs
  2009-02-12 18:42     ` Eric Sandeen
@ 2009-02-12 18:51       ` Christoph Hellwig
  0 siblings, 0 replies; 22+ messages in thread
From: Christoph Hellwig @ 2009-02-12 18:51 UTC (permalink / raw)
  To: Eric Sandeen; +Cc: Christoph Hellwig, Josef 'Jeff' Sipek, xfs

On Thu, Feb 12, 2009 at 12:42:02PM -0600, Eric Sandeen wrote:
> Josef 'Jeff' Sipek wrote:
> > On Tue, Feb 10, 2009 at 03:22:53PM -0500, Christoph Hellwig wrote:
> > ...
> >> Index: xfs/fs/xfs/xfs_dinode.h
> >> ===================================================================
> >> --- xfs.orig/fs/xfs/xfs_dinode.h	2009-02-10 19:45:51.939069576 +0100
> >> +++ xfs/fs/xfs/xfs_dinode.h	2009-02-10 19:45:59.195068745 +0100
> >> @@ -69,11 +69,32 @@ typedef struct xfs_dinode {
> >>  
> >>  	/* di_next_unlinked is the only non-core field in the old dinode */
> >>  	__be32		di_next_unlinked;/* agi unlinked list ptr */
> >> -} __attribute__((packed)) xfs_dinode_t;
> >> +
> >> +	/* start of the extended dinode, writable fields */
> >> +	__be32		di_crc;		/* CRC of the inode */
> >> +	__be64		di_changecount;	/* number of attribute changes */
> >> +	__u8		di_pad2[16];	/* more padding for future expansion */
> >> +
> >> +	/* fields only written to during inode creation */
> >> +	xfs_timestamp_t	di_crtime;	/* time created */
> >> +	__be64		di_ino;		/* inode number */
> >> +	uuid_t		di_uuid;	/* UUID of the filesystem */
> >> +} xfs_dinode_t;
> > 
> > Hrm...removing the packed attribute... Eric, do you remember the ARM ABI
> > alignment rules? Regardless of ARM, are those fields aligned nicely? (From a
> > quick glance at the code looks ok.)
> 
> I'll just have to just test it again I suppose.  Removing packed is
> good, as long as the padding makes it all come out right.

The reason why the current dinode needs the packed attribute is that
it's end on an un-even 32bit word, and thus the last field might be
wrongly aligned on 64-bit big-endian platforms (same issue as the
bad features2 one).  With the CRC patchset we now have a dinode
that's properly aligned on a even 32bit word.

> 
> -=Eric
---end quoted text---

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

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 13/13] xfs: add CRC checks for quota blocks
  2009-02-12  6:41   ` Josef 'Jeff' Sipek
@ 2009-02-13 20:10     ` Christoph Hellwig
  0 siblings, 0 replies; 22+ messages in thread
From: Christoph Hellwig @ 2009-02-13 20:10 UTC (permalink / raw)
  To: Josef 'Jeff' Sipek; +Cc: Christoph Hellwig, xfs

On Thu, Feb 12, 2009 at 01:41:28AM -0500, Josef 'Jeff' Sipek wrote:
> >  	xfs_disk_dquot_t  dd_diskdq;	/* portion that lives incore as well */
> > -	char		  dd_fill[32];	/* filling for posterity */
> > +	char		  dd_fill[12];	/* filling for posterity */
> > +
> > +	/*
> > +	 * These two are only present one filesystems with the CRC bits set.
> > +	 */
> > +	__be32		  dd_crc;	/* checksum */
> > +	uuid_t		  dd_uuid;	/* location information */
> >  } xfs_dqblk_t;
> 
> Again, why put the crc/uuid at the end?

So that we can add additional infos either to xfs_disk_dquot_t
(preserved in-core) or xfs_dqblk_t (purly on-disk).

> > +		if (!xfs_verify_cksum((char *)d, sizeof(struct xfs_dqblk),
> > +				 offsetof(struct xfs_dqblk, dd_crc))) {
> > +//		    !uuid_equal(&agfl->agfl_uuid, &mp->m_sb.sb_uuid) ||
> 
> Dead code?

Sorry, sent out a too early version.  The final patch actually verifies
the uuid and the correct location in the quota file.

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

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 10/13] xfs: add CRC checks to the AGFL
  2009-02-11  7:54   ` Dave Chinner
@ 2009-02-15 18:23     ` Christoph Hellwig
  0 siblings, 0 replies; 22+ messages in thread
From: Christoph Hellwig @ 2009-02-15 18:23 UTC (permalink / raw)
  To: Christoph Hellwig, xfs

On Wed, Feb 11, 2009 at 06:54:33PM +1100, Dave Chinner wrote:
> I haven't had a chance to look over any of this series in detail - just
> a quick glance really - but this popped out as looking wrong:
> 
> > +/*
> > + * 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))
> 
> sb_sectsize is in bytes, sizeof(xfs_agblock_t) is in bytes, which
> means that the numerator is a count of the number of agblocks that
> will fit in the AGFL. sizeof(struct xfs_agfl) is also in bytes,
> so your subtracting a number of bytes from a count of agblocks....
> 
> I think you mean:
> 
> #define XFS_AGFL_SIZE(mp) \
> 	(((mp)->m_sb.sb_sectsize - (xfs_sb_version_hascrc(&((mp)->m_sb)) ? \
> 						sizeof(struct xfs_agfl) : 0)) \
> 	  / sizeof(xfs_agblock_t))

Yeah.  Either that, or dividing the sizeof by four.

> >  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;
> 
> And judging by that you are stealing more than 2 slots - more like
> 8 slots.

Yeah, two slots was the very first implementation, I'll fix up the
comment too.

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

^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2009-02-15 18:24 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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 ` [PATCH 10/13] xfs: add CRC checks to the AGFL Christoph Hellwig
2009-02-11  7:54   ` 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

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.