xfs: add version 3 inode format with CRCs

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);
	a changecount (for NFSv4);
	a flush sequence (in LSN format for recovery);
	an additional inode flags field; and
	some additional padding.

These additional fields are not implemented yet, but already laid
out in the structure.

[dchinner@redhat.com] Added LSN and flags field, some factoring and rework to
capture all the necessary information in the crc calculation.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Ben Myers <bpm@sgi.com>
Signed-off-by: Ben Myers <bpm@sgi.com>
This commit is contained in:
Christoph Hellwig 2013-04-03 16:11:17 +11:00 committed by Ben Myers
parent 3fe58f30b4
commit 93848a999c
8 changed files with 254 additions and 77 deletions

View file

@ -1786,6 +1786,7 @@ xlog_recover_do_inode_buffer(
xfs_agino_t *buffer_nextp;
trace_xfs_log_recover_buf_inode_buf(mp->m_log, buf_f);
bp->b_ops = &xfs_inode_buf_ops;
inodes_per_buf = BBTOB(bp->b_io_length) >> mp->m_sb.sb_inodelog;
for (i = 0; i < inodes_per_buf; i++) {
@ -1989,6 +1990,18 @@ xlog_recover_do_reg_buffer(
}
bp->b_ops = &xfs_dquot_buf_ops;
break;
case XFS_BLF_DINO_BUF:
/*
* we get here with inode allocation buffers, not buffers that
* track unlinked list changes.
*/
if (*(__be16 *)bp->b_addr != cpu_to_be16(XFS_DINODE_MAGIC)) {
xfs_warn(mp, "Bad INODE block magic!");
ASSERT(0);
break;
}
bp->b_ops = &xfs_inode_buf_ops;
break;
default:
break;
}
@ -2277,6 +2290,7 @@ xlog_recover_inode_pass2(
int attr_index;
uint fields;
xfs_icdinode_t *dicp;
uint isize;
int need_free = 0;
if (item->ri_buf[0].i_len == sizeof(xfs_inode_log_format_t)) {
@ -2302,7 +2316,7 @@ xlog_recover_inode_pass2(
trace_xfs_log_recover_inode_recover(log, in_f);
bp = xfs_buf_read(mp->m_ddev_targp, in_f->ilf_blkno, in_f->ilf_len, 0,
NULL);
&xfs_inode_buf_ops);
if (!bp) {
error = ENOMEM;
goto error;
@ -2413,7 +2427,8 @@ xlog_recover_inode_pass2(
error = EFSCORRUPTED;
goto error;
}
if (unlikely(item->ri_buf[1].i_len > sizeof(struct xfs_icdinode))) {
isize = xfs_icdinode_size(dicp->di_version);
if (unlikely(item->ri_buf[1].i_len > isize)) {
XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(7)",
XFS_ERRLEVEL_LOW, mp, dicp);
xfs_buf_relse(bp);
@ -2425,13 +2440,13 @@ xlog_recover_inode_pass2(
}
/* The core is in in-core format */
xfs_dinode_to_disk(dip, 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((char *)dip + isize,
item->ri_buf[1].i_addr + isize,
item->ri_buf[1].i_len - isize);
}
fields = in_f->ilf_fields;
@ -2515,6 +2530,9 @@ xlog_recover_inode_pass2(
}
write_inode_buffer:
/* re-generate the checksum. */
xfs_dinode_calc_crc(log->l_mp, dip);
ASSERT(bp->b_target->bt_mount == mp);
bp->b_iodone = xlog_recover_iodone;
xfs_buf_delwri_queue(bp, buffer_list);