aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_log_recover.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_log_recover.c')
-rw-r--r--fs/xfs/xfs_log_recover.c97
1 files changed, 53 insertions, 44 deletions
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index be5568839442..396565f43247 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -190,7 +190,7 @@ xlog_bread_noalign(
190 ASSERT(nbblks <= bp->b_length); 190 ASSERT(nbblks <= bp->b_length);
191 191
192 XFS_BUF_SET_ADDR(bp, log->l_logBBstart + blk_no); 192 XFS_BUF_SET_ADDR(bp, log->l_logBBstart + blk_no);
193 XFS_BUF_READ(bp); 193 bp->b_flags |= XBF_READ;
194 bp->b_io_length = nbblks; 194 bp->b_io_length = nbblks;
195 bp->b_error = 0; 195 bp->b_error = 0;
196 196
@@ -275,7 +275,6 @@ xlog_bwrite(
275 ASSERT(nbblks <= bp->b_length); 275 ASSERT(nbblks <= bp->b_length);
276 276
277 XFS_BUF_SET_ADDR(bp, log->l_logBBstart + blk_no); 277 XFS_BUF_SET_ADDR(bp, log->l_logBBstart + blk_no);
278 XFS_BUF_ZEROFLAGS(bp);
279 xfs_buf_hold(bp); 278 xfs_buf_hold(bp);
280 xfs_buf_lock(bp); 279 xfs_buf_lock(bp);
281 bp->b_io_length = nbblks; 280 bp->b_io_length = nbblks;
@@ -2538,6 +2537,13 @@ xlog_recover_validate_buf_type(
2538 } 2537 }
2539 bp->b_ops = &xfs_sb_buf_ops; 2538 bp->b_ops = &xfs_sb_buf_ops;
2540 break; 2539 break;
2540#ifdef CONFIG_XFS_RT
2541 case XFS_BLFT_RTBITMAP_BUF:
2542 case XFS_BLFT_RTSUMMARY_BUF:
2543 /* no magic numbers for verification of RT buffers */
2544 bp->b_ops = &xfs_rtbuf_ops;
2545 break;
2546#endif /* CONFIG_XFS_RT */
2541 default: 2547 default:
2542 xfs_warn(mp, "Unknown buffer type %d!", 2548 xfs_warn(mp, "Unknown buffer type %d!",
2543 xfs_blft_from_flags(buf_f)); 2549 xfs_blft_from_flags(buf_f));
@@ -2858,7 +2864,7 @@ xfs_recover_inode_owner_change(
2858 return -ENOMEM; 2864 return -ENOMEM;
2859 2865
2860 /* instantiate the inode */ 2866 /* instantiate the inode */
2861 xfs_dinode_from_disk(&ip->i_d, dip); 2867 xfs_inode_from_disk(ip, dip);
2862 ASSERT(ip->i_d.di_version >= 3); 2868 ASSERT(ip->i_d.di_version >= 3);
2863 2869
2864 error = xfs_iformat_fork(ip, dip); 2870 error = xfs_iformat_fork(ip, dip);
@@ -2904,7 +2910,7 @@ xlog_recover_inode_pass2(
2904 int error; 2910 int error;
2905 int attr_index; 2911 int attr_index;
2906 uint fields; 2912 uint fields;
2907 xfs_icdinode_t *dicp; 2913 struct xfs_log_dinode *ldip;
2908 uint isize; 2914 uint isize;
2909 int need_free = 0; 2915 int need_free = 0;
2910 2916
@@ -2957,8 +2963,8 @@ xlog_recover_inode_pass2(
2957 error = -EFSCORRUPTED; 2963 error = -EFSCORRUPTED;
2958 goto out_release; 2964 goto out_release;
2959 } 2965 }
2960 dicp = item->ri_buf[1].i_addr; 2966 ldip = item->ri_buf[1].i_addr;
2961 if (unlikely(dicp->di_magic != XFS_DINODE_MAGIC)) { 2967 if (unlikely(ldip->di_magic != XFS_DINODE_MAGIC)) {
2962 xfs_alert(mp, 2968 xfs_alert(mp,
2963 "%s: Bad inode log record, rec ptr 0x%p, ino %Ld", 2969 "%s: Bad inode log record, rec ptr 0x%p, ino %Ld",
2964 __func__, item, in_f->ilf_ino); 2970 __func__, item, in_f->ilf_ino);
@@ -2994,13 +3000,13 @@ xlog_recover_inode_pass2(
2994 * to skip replay when the on disk inode is newer than the log one 3000 * to skip replay when the on disk inode is newer than the log one
2995 */ 3001 */
2996 if (!xfs_sb_version_hascrc(&mp->m_sb) && 3002 if (!xfs_sb_version_hascrc(&mp->m_sb) &&
2997 dicp->di_flushiter < be16_to_cpu(dip->di_flushiter)) { 3003 ldip->di_flushiter < be16_to_cpu(dip->di_flushiter)) {
2998 /* 3004 /*
2999 * Deal with the wrap case, DI_MAX_FLUSH is less 3005 * Deal with the wrap case, DI_MAX_FLUSH is less
3000 * than smaller numbers 3006 * than smaller numbers
3001 */ 3007 */
3002 if (be16_to_cpu(dip->di_flushiter) == DI_MAX_FLUSH && 3008 if (be16_to_cpu(dip->di_flushiter) == DI_MAX_FLUSH &&
3003 dicp->di_flushiter < (DI_MAX_FLUSH >> 1)) { 3009 ldip->di_flushiter < (DI_MAX_FLUSH >> 1)) {
3004 /* do nothing */ 3010 /* do nothing */
3005 } else { 3011 } else {
3006 trace_xfs_log_recover_inode_skip(log, in_f); 3012 trace_xfs_log_recover_inode_skip(log, in_f);
@@ -3010,13 +3016,13 @@ xlog_recover_inode_pass2(
3010 } 3016 }
3011 3017
3012 /* Take the opportunity to reset the flush iteration count */ 3018 /* Take the opportunity to reset the flush iteration count */
3013 dicp->di_flushiter = 0; 3019 ldip->di_flushiter = 0;
3014 3020
3015 if (unlikely(S_ISREG(dicp->di_mode))) { 3021 if (unlikely(S_ISREG(ldip->di_mode))) {
3016 if ((dicp->di_format != XFS_DINODE_FMT_EXTENTS) && 3022 if ((ldip->di_format != XFS_DINODE_FMT_EXTENTS) &&
3017 (dicp->di_format != XFS_DINODE_FMT_BTREE)) { 3023 (ldip->di_format != XFS_DINODE_FMT_BTREE)) {
3018 XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(3)", 3024 XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(3)",
3019 XFS_ERRLEVEL_LOW, mp, dicp); 3025 XFS_ERRLEVEL_LOW, mp, ldip);
3020 xfs_alert(mp, 3026 xfs_alert(mp,
3021 "%s: Bad regular inode log record, rec ptr 0x%p, " 3027 "%s: Bad regular inode log record, rec ptr 0x%p, "
3022 "ino ptr = 0x%p, ino bp = 0x%p, ino %Ld", 3028 "ino ptr = 0x%p, ino bp = 0x%p, ino %Ld",
@@ -3024,12 +3030,12 @@ xlog_recover_inode_pass2(
3024 error = -EFSCORRUPTED; 3030 error = -EFSCORRUPTED;
3025 goto out_release; 3031 goto out_release;
3026 } 3032 }
3027 } else if (unlikely(S_ISDIR(dicp->di_mode))) { 3033 } else if (unlikely(S_ISDIR(ldip->di_mode))) {
3028 if ((dicp->di_format != XFS_DINODE_FMT_EXTENTS) && 3034 if ((ldip->di_format != XFS_DINODE_FMT_EXTENTS) &&
3029 (dicp->di_format != XFS_DINODE_FMT_BTREE) && 3035 (ldip->di_format != XFS_DINODE_FMT_BTREE) &&
3030 (dicp->di_format != XFS_DINODE_FMT_LOCAL)) { 3036 (ldip->di_format != XFS_DINODE_FMT_LOCAL)) {
3031 XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(4)", 3037 XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(4)",
3032 XFS_ERRLEVEL_LOW, mp, dicp); 3038 XFS_ERRLEVEL_LOW, mp, ldip);
3033 xfs_alert(mp, 3039 xfs_alert(mp,
3034 "%s: Bad dir inode log record, rec ptr 0x%p, " 3040 "%s: Bad dir inode log record, rec ptr 0x%p, "
3035 "ino ptr = 0x%p, ino bp = 0x%p, ino %Ld", 3041 "ino ptr = 0x%p, ino bp = 0x%p, ino %Ld",
@@ -3038,32 +3044,32 @@ xlog_recover_inode_pass2(
3038 goto out_release; 3044 goto out_release;
3039 } 3045 }
3040 } 3046 }
3041 if (unlikely(dicp->di_nextents + dicp->di_anextents > dicp->di_nblocks)){ 3047 if (unlikely(ldip->di_nextents + ldip->di_anextents > ldip->di_nblocks)){
3042 XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(5)", 3048 XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(5)",
3043 XFS_ERRLEVEL_LOW, mp, dicp); 3049 XFS_ERRLEVEL_LOW, mp, ldip);
3044 xfs_alert(mp, 3050 xfs_alert(mp,
3045 "%s: Bad inode log record, rec ptr 0x%p, dino ptr 0x%p, " 3051 "%s: Bad inode log record, rec ptr 0x%p, dino ptr 0x%p, "
3046 "dino bp 0x%p, ino %Ld, total extents = %d, nblocks = %Ld", 3052 "dino bp 0x%p, ino %Ld, total extents = %d, nblocks = %Ld",
3047 __func__, item, dip, bp, in_f->ilf_ino, 3053 __func__, item, dip, bp, in_f->ilf_ino,
3048 dicp->di_nextents + dicp->di_anextents, 3054 ldip->di_nextents + ldip->di_anextents,
3049 dicp->di_nblocks); 3055 ldip->di_nblocks);
3050 error = -EFSCORRUPTED; 3056 error = -EFSCORRUPTED;
3051 goto out_release; 3057 goto out_release;
3052 } 3058 }
3053 if (unlikely(dicp->di_forkoff > mp->m_sb.sb_inodesize)) { 3059 if (unlikely(ldip->di_forkoff > mp->m_sb.sb_inodesize)) {
3054 XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(6)", 3060 XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(6)",
3055 XFS_ERRLEVEL_LOW, mp, dicp); 3061 XFS_ERRLEVEL_LOW, mp, ldip);
3056 xfs_alert(mp, 3062 xfs_alert(mp,
3057 "%s: Bad inode log record, rec ptr 0x%p, dino ptr 0x%p, " 3063 "%s: Bad inode log record, rec ptr 0x%p, dino ptr 0x%p, "
3058 "dino bp 0x%p, ino %Ld, forkoff 0x%x", __func__, 3064 "dino bp 0x%p, ino %Ld, forkoff 0x%x", __func__,
3059 item, dip, bp, in_f->ilf_ino, dicp->di_forkoff); 3065 item, dip, bp, in_f->ilf_ino, ldip->di_forkoff);
3060 error = -EFSCORRUPTED; 3066 error = -EFSCORRUPTED;
3061 goto out_release; 3067 goto out_release;
3062 } 3068 }
3063 isize = xfs_icdinode_size(dicp->di_version); 3069 isize = xfs_log_dinode_size(ldip->di_version);
3064 if (unlikely(item->ri_buf[1].i_len > isize)) { 3070 if (unlikely(item->ri_buf[1].i_len > isize)) {
3065 XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(7)", 3071 XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(7)",
3066 XFS_ERRLEVEL_LOW, mp, dicp); 3072 XFS_ERRLEVEL_LOW, mp, ldip);
3067 xfs_alert(mp, 3073 xfs_alert(mp,
3068 "%s: Bad inode log record length %d, rec ptr 0x%p", 3074 "%s: Bad inode log record length %d, rec ptr 0x%p",
3069 __func__, item->ri_buf[1].i_len, item); 3075 __func__, item->ri_buf[1].i_len, item);
@@ -3071,8 +3077,8 @@ xlog_recover_inode_pass2(
3071 goto out_release; 3077 goto out_release;
3072 } 3078 }
3073 3079
3074 /* The core is in in-core format */ 3080 /* recover the log dinode inode into the on disk inode */
3075 xfs_dinode_to_disk(dip, dicp); 3081 xfs_log_dinode_to_disk(ldip, dip);
3076 3082
3077 /* the rest is in on-disk format */ 3083 /* the rest is in on-disk format */
3078 if (item->ri_buf[1].i_len > isize) { 3084 if (item->ri_buf[1].i_len > isize) {
@@ -4402,8 +4408,8 @@ xlog_recover_process_one_iunlink(
4402 if (error) 4408 if (error)
4403 goto fail_iput; 4409 goto fail_iput;
4404 4410
4405 ASSERT(ip->i_d.di_nlink == 0); 4411 ASSERT(VFS_I(ip)->i_nlink == 0);
4406 ASSERT(ip->i_d.di_mode != 0); 4412 ASSERT(VFS_I(ip)->i_mode != 0);
4407 4413
4408 /* setup for the next pass */ 4414 /* setup for the next pass */
4409 agino = be32_to_cpu(dip->di_next_unlinked); 4415 agino = be32_to_cpu(dip->di_next_unlinked);
@@ -4957,6 +4963,7 @@ xlog_do_recover(
4957 xfs_daddr_t head_blk, 4963 xfs_daddr_t head_blk,
4958 xfs_daddr_t tail_blk) 4964 xfs_daddr_t tail_blk)
4959{ 4965{
4966 struct xfs_mount *mp = log->l_mp;
4960 int error; 4967 int error;
4961 xfs_buf_t *bp; 4968 xfs_buf_t *bp;
4962 xfs_sb_t *sbp; 4969 xfs_sb_t *sbp;
@@ -4971,7 +4978,7 @@ xlog_do_recover(
4971 /* 4978 /*
4972 * If IO errors happened during recovery, bail out. 4979 * If IO errors happened during recovery, bail out.
4973 */ 4980 */
4974 if (XFS_FORCED_SHUTDOWN(log->l_mp)) { 4981 if (XFS_FORCED_SHUTDOWN(mp)) {
4975 return -EIO; 4982 return -EIO;
4976 } 4983 }
4977 4984
@@ -4984,22 +4991,21 @@ xlog_do_recover(
4984 * or iunlinks they will have some entries in the AIL; so we look at 4991 * or iunlinks they will have some entries in the AIL; so we look at
4985 * the AIL to determine how to set the tail_lsn. 4992 * the AIL to determine how to set the tail_lsn.
4986 */ 4993 */
4987 xlog_assign_tail_lsn(log->l_mp); 4994 xlog_assign_tail_lsn(mp);
4988 4995
4989 /* 4996 /*
4990 * Now that we've finished replaying all buffer and inode 4997 * Now that we've finished replaying all buffer and inode
4991 * updates, re-read in the superblock and reverify it. 4998 * updates, re-read in the superblock and reverify it.
4992 */ 4999 */
4993 bp = xfs_getsb(log->l_mp, 0); 5000 bp = xfs_getsb(mp, 0);
4994 XFS_BUF_UNDONE(bp); 5001 bp->b_flags &= ~(XBF_DONE | XBF_ASYNC);
4995 ASSERT(!(XFS_BUF_ISWRITE(bp))); 5002 ASSERT(!(bp->b_flags & XBF_WRITE));
4996 XFS_BUF_READ(bp); 5003 bp->b_flags |= XBF_READ;
4997 XFS_BUF_UNASYNC(bp);
4998 bp->b_ops = &xfs_sb_buf_ops; 5004 bp->b_ops = &xfs_sb_buf_ops;
4999 5005
5000 error = xfs_buf_submit_wait(bp); 5006 error = xfs_buf_submit_wait(bp);
5001 if (error) { 5007 if (error) {
5002 if (!XFS_FORCED_SHUTDOWN(log->l_mp)) { 5008 if (!XFS_FORCED_SHUTDOWN(mp)) {
5003 xfs_buf_ioerror_alert(bp, __func__); 5009 xfs_buf_ioerror_alert(bp, __func__);
5004 ASSERT(0); 5010 ASSERT(0);
5005 } 5011 }
@@ -5008,14 +5014,17 @@ xlog_do_recover(
5008 } 5014 }
5009 5015
5010 /* Convert superblock from on-disk format */ 5016 /* Convert superblock from on-disk format */
5011 sbp = &log->l_mp->m_sb; 5017 sbp = &mp->m_sb;
5012 xfs_sb_from_disk(sbp, XFS_BUF_TO_SBP(bp)); 5018 xfs_sb_from_disk(sbp, XFS_BUF_TO_SBP(bp));
5013 ASSERT(sbp->sb_magicnum == XFS_SB_MAGIC);
5014 ASSERT(xfs_sb_good_version(sbp));
5015 xfs_reinit_percpu_counters(log->l_mp);
5016
5017 xfs_buf_relse(bp); 5019 xfs_buf_relse(bp);
5018 5020
5021 /* re-initialise in-core superblock and geometry structures */
5022 xfs_reinit_percpu_counters(mp);
5023 error = xfs_initialize_perag(mp, sbp->sb_agcount, &mp->m_maxagi);
5024 if (error) {
5025 xfs_warn(mp, "Failed post-recovery per-ag init: %d", error);
5026 return error;
5027 }
5019 5028
5020 xlog_recover_check_summary(log); 5029 xlog_recover_check_summary(log);
5021 5030