aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_log_recover.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2013-04-03 01:11:17 -0400
committerBen Myers <bpm@sgi.com>2013-04-21 16:03:33 -0400
commit93848a999cf9b9e4f4f77dba843a48c393f33c59 (patch)
tree92c2fb4e741a8d70e70f9d31df308d1a30ecaef6 /fs/xfs/xfs_log_recover.c
parent3fe58f30b4fc3f8a9084b035a02bc0c67bee8d00 (diff)
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>
Diffstat (limited to 'fs/xfs/xfs_log_recover.c')
-rw-r--r--fs/xfs/xfs_log_recover.c32
1 files changed, 25 insertions, 7 deletions
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index 27b3ec214a67..287878219af7 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -1786,6 +1786,7 @@ xlog_recover_do_inode_buffer(
1786 xfs_agino_t *buffer_nextp; 1786 xfs_agino_t *buffer_nextp;
1787 1787
1788 trace_xfs_log_recover_buf_inode_buf(mp->m_log, buf_f); 1788 trace_xfs_log_recover_buf_inode_buf(mp->m_log, buf_f);
1789 bp->b_ops = &xfs_inode_buf_ops;
1789 1790
1790 inodes_per_buf = BBTOB(bp->b_io_length) >> mp->m_sb.sb_inodelog; 1791 inodes_per_buf = BBTOB(bp->b_io_length) >> mp->m_sb.sb_inodelog;
1791 for (i = 0; i < inodes_per_buf; i++) { 1792 for (i = 0; i < inodes_per_buf; i++) {
@@ -1989,6 +1990,18 @@ xlog_recover_do_reg_buffer(
1989 } 1990 }
1990 bp->b_ops = &xfs_dquot_buf_ops; 1991 bp->b_ops = &xfs_dquot_buf_ops;
1991 break; 1992 break;
1993 case XFS_BLF_DINO_BUF:
1994 /*
1995 * we get here with inode allocation buffers, not buffers that
1996 * track unlinked list changes.
1997 */
1998 if (*(__be16 *)bp->b_addr != cpu_to_be16(XFS_DINODE_MAGIC)) {
1999 xfs_warn(mp, "Bad INODE block magic!");
2000 ASSERT(0);
2001 break;
2002 }
2003 bp->b_ops = &xfs_inode_buf_ops;
2004 break;
1992 default: 2005 default:
1993 break; 2006 break;
1994 } 2007 }
@@ -2277,6 +2290,7 @@ xlog_recover_inode_pass2(
2277 int attr_index; 2290 int attr_index;
2278 uint fields; 2291 uint fields;
2279 xfs_icdinode_t *dicp; 2292 xfs_icdinode_t *dicp;
2293 uint isize;
2280 int need_free = 0; 2294 int need_free = 0;
2281 2295
2282 if (item->ri_buf[0].i_len == sizeof(xfs_inode_log_format_t)) { 2296 if (item->ri_buf[0].i_len == sizeof(xfs_inode_log_format_t)) {
@@ -2302,7 +2316,7 @@ xlog_recover_inode_pass2(
2302 trace_xfs_log_recover_inode_recover(log, in_f); 2316 trace_xfs_log_recover_inode_recover(log, in_f);
2303 2317
2304 bp = xfs_buf_read(mp->m_ddev_targp, in_f->ilf_blkno, in_f->ilf_len, 0, 2318 bp = xfs_buf_read(mp->m_ddev_targp, in_f->ilf_blkno, in_f->ilf_len, 0,
2305 NULL); 2319 &xfs_inode_buf_ops);
2306 if (!bp) { 2320 if (!bp) {
2307 error = ENOMEM; 2321 error = ENOMEM;
2308 goto error; 2322 goto error;
@@ -2413,7 +2427,8 @@ xlog_recover_inode_pass2(
2413 error = EFSCORRUPTED; 2427 error = EFSCORRUPTED;
2414 goto error; 2428 goto error;
2415 } 2429 }
2416 if (unlikely(item->ri_buf[1].i_len > sizeof(struct xfs_icdinode))) { 2430 isize = xfs_icdinode_size(dicp->di_version);
2431 if (unlikely(item->ri_buf[1].i_len > isize)) {
2417 XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(7)", 2432 XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(7)",
2418 XFS_ERRLEVEL_LOW, mp, dicp); 2433 XFS_ERRLEVEL_LOW, mp, dicp);
2419 xfs_buf_relse(bp); 2434 xfs_buf_relse(bp);
@@ -2425,13 +2440,13 @@ xlog_recover_inode_pass2(
2425 } 2440 }
2426 2441
2427 /* The core is in in-core format */ 2442 /* The core is in in-core format */
2428 xfs_dinode_to_disk(dip, item->ri_buf[1].i_addr); 2443 xfs_dinode_to_disk(dip, dicp);
2429 2444
2430 /* the rest is in on-disk format */ 2445 /* the rest is in on-disk format */
2431 if (item->ri_buf[1].i_len > sizeof(struct xfs_icdinode)) { 2446 if (item->ri_buf[1].i_len > isize) {
2432 memcpy((xfs_caddr_t) dip + sizeof(struct xfs_icdinode), 2447 memcpy((char *)dip + isize,
2433 item->ri_buf[1].i_addr + sizeof(struct xfs_icdinode), 2448 item->ri_buf[1].i_addr + isize,
2434 item->ri_buf[1].i_len - sizeof(struct xfs_icdinode)); 2449 item->ri_buf[1].i_len - isize);
2435 } 2450 }
2436 2451
2437 fields = in_f->ilf_fields; 2452 fields = in_f->ilf_fields;
@@ -2515,6 +2530,9 @@ xlog_recover_inode_pass2(
2515 } 2530 }
2516 2531
2517write_inode_buffer: 2532write_inode_buffer:
2533 /* re-generate the checksum. */
2534 xfs_dinode_calc_crc(log->l_mp, dip);
2535
2518 ASSERT(bp->b_target->bt_mount == mp); 2536 ASSERT(bp->b_target->bt_mount == mp);
2519 bp->b_iodone = xlog_recover_iodone; 2537 bp->b_iodone = xlog_recover_iodone;
2520 xfs_buf_delwri_queue(bp, buffer_list); 2538 xfs_buf_delwri_queue(bp, buffer_list);