diff options
Diffstat (limited to 'fs/xfs/xfs_log_recover.c')
-rw-r--r-- | fs/xfs/xfs_log_recover.c | 97 |
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 | ||