diff options
author | Christoph Hellwig <hch@lst.de> | 2013-04-03 01:11:17 -0400 |
---|---|---|
committer | Ben Myers <bpm@sgi.com> | 2013-04-21 16:03:33 -0400 |
commit | 93848a999cf9b9e4f4f77dba843a48c393f33c59 (patch) | |
tree | 92c2fb4e741a8d70e70f9d31df308d1a30ecaef6 /fs/xfs/xfs_log_recover.c | |
parent | 3fe58f30b4fc3f8a9084b035a02bc0c67bee8d00 (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.c | 32 |
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 | ||
2517 | write_inode_buffer: | 2532 | write_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); |