diff options
author | Tim Shimmin <tes@sgi.com> | 2006-06-09 00:55:38 -0400 |
---|---|---|
committer | Nathan Scott <nathans@sgi.com> | 2006-06-09 00:55:38 -0400 |
commit | 6d192a9b82212abf1e0e89da6e3a952afba7e4d6 (patch) | |
tree | 608a463ba4fd04f518558ead3567952e757cd2ae /fs/xfs/xfs_log_recover.c | |
parent | d210a28cd851082cec9b282443f8cc0e6fc09830 (diff) |
[XFS] inode items and EFI/EFDs have different ondisk format for 32bit and
64bit kernels allow recovery to handle both versions and do the necessary
decoding
SGI-PV: 952214
SGI-Modid: xfs-linux-melb:xfs-kern:26011a
Signed-off-by: Tim Shimmin <tes@sgi.com>
Signed-off-by: Nathan Scott <nathans@sgi.com>
Diffstat (limited to 'fs/xfs/xfs_log_recover.c')
-rw-r--r-- | fs/xfs/xfs_log_recover.c | 87 |
1 files changed, 56 insertions, 31 deletions
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 1f0016b0b4ec..efffa75fd5cf 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c | |||
@@ -2292,12 +2292,22 @@ xlog_recover_do_inode_trans( | |||
2292 | int attr_index; | 2292 | int attr_index; |
2293 | uint fields; | 2293 | uint fields; |
2294 | xfs_dinode_core_t *dicp; | 2294 | xfs_dinode_core_t *dicp; |
2295 | int need_free = 0; | ||
2295 | 2296 | ||
2296 | if (pass == XLOG_RECOVER_PASS1) { | 2297 | if (pass == XLOG_RECOVER_PASS1) { |
2297 | return 0; | 2298 | return 0; |
2298 | } | 2299 | } |
2299 | 2300 | ||
2300 | in_f = (xfs_inode_log_format_t *)item->ri_buf[0].i_addr; | 2301 | if (item->ri_buf[0].i_len == sizeof(xfs_inode_log_format_t)) { |
2302 | in_f = (xfs_inode_log_format_t *)item->ri_buf[0].i_addr; | ||
2303 | } else { | ||
2304 | in_f = (xfs_inode_log_format_t *)kmem_alloc( | ||
2305 | sizeof(xfs_inode_log_format_t), KM_SLEEP); | ||
2306 | need_free = 1; | ||
2307 | error = xfs_inode_item_format_convert(&item->ri_buf[0], in_f); | ||
2308 | if (error) | ||
2309 | goto error; | ||
2310 | } | ||
2301 | ino = in_f->ilf_ino; | 2311 | ino = in_f->ilf_ino; |
2302 | mp = log->l_mp; | 2312 | mp = log->l_mp; |
2303 | if (ITEM_TYPE(item) == XFS_LI_INODE) { | 2313 | if (ITEM_TYPE(item) == XFS_LI_INODE) { |
@@ -2323,8 +2333,10 @@ xlog_recover_do_inode_trans( | |||
2323 | * Inode buffers can be freed, look out for it, | 2333 | * Inode buffers can be freed, look out for it, |
2324 | * and do not replay the inode. | 2334 | * and do not replay the inode. |
2325 | */ | 2335 | */ |
2326 | if (xlog_check_buffer_cancelled(log, imap.im_blkno, imap.im_len, 0)) | 2336 | if (xlog_check_buffer_cancelled(log, imap.im_blkno, imap.im_len, 0)) { |
2327 | return 0; | 2337 | error = 0; |
2338 | goto error; | ||
2339 | } | ||
2328 | 2340 | ||
2329 | bp = xfs_buf_read_flags(mp->m_ddev_targp, imap.im_blkno, imap.im_len, | 2341 | bp = xfs_buf_read_flags(mp->m_ddev_targp, imap.im_blkno, imap.im_len, |
2330 | XFS_BUF_LOCK); | 2342 | XFS_BUF_LOCK); |
@@ -2333,7 +2345,7 @@ xlog_recover_do_inode_trans( | |||
2333 | bp, imap.im_blkno); | 2345 | bp, imap.im_blkno); |
2334 | error = XFS_BUF_GETERROR(bp); | 2346 | error = XFS_BUF_GETERROR(bp); |
2335 | xfs_buf_relse(bp); | 2347 | xfs_buf_relse(bp); |
2336 | return error; | 2348 | goto error; |
2337 | } | 2349 | } |
2338 | error = 0; | 2350 | error = 0; |
2339 | ASSERT(in_f->ilf_fields & XFS_ILOG_CORE); | 2351 | ASSERT(in_f->ilf_fields & XFS_ILOG_CORE); |
@@ -2350,7 +2362,8 @@ xlog_recover_do_inode_trans( | |||
2350 | dip, bp, ino); | 2362 | dip, bp, ino); |
2351 | XFS_ERROR_REPORT("xlog_recover_do_inode_trans(1)", | 2363 | XFS_ERROR_REPORT("xlog_recover_do_inode_trans(1)", |
2352 | XFS_ERRLEVEL_LOW, mp); | 2364 | XFS_ERRLEVEL_LOW, mp); |
2353 | return XFS_ERROR(EFSCORRUPTED); | 2365 | error = EFSCORRUPTED; |
2366 | goto error; | ||
2354 | } | 2367 | } |
2355 | dicp = (xfs_dinode_core_t*)(item->ri_buf[1].i_addr); | 2368 | dicp = (xfs_dinode_core_t*)(item->ri_buf[1].i_addr); |
2356 | if (unlikely(dicp->di_magic != XFS_DINODE_MAGIC)) { | 2369 | if (unlikely(dicp->di_magic != XFS_DINODE_MAGIC)) { |
@@ -2360,7 +2373,8 @@ xlog_recover_do_inode_trans( | |||
2360 | item, ino); | 2373 | item, ino); |
2361 | XFS_ERROR_REPORT("xlog_recover_do_inode_trans(2)", | 2374 | XFS_ERROR_REPORT("xlog_recover_do_inode_trans(2)", |
2362 | XFS_ERRLEVEL_LOW, mp); | 2375 | XFS_ERRLEVEL_LOW, mp); |
2363 | return XFS_ERROR(EFSCORRUPTED); | 2376 | error = EFSCORRUPTED; |
2377 | goto error; | ||
2364 | } | 2378 | } |
2365 | 2379 | ||
2366 | /* Skip replay when the on disk inode is newer than the log one */ | 2380 | /* Skip replay when the on disk inode is newer than the log one */ |
@@ -2376,7 +2390,8 @@ xlog_recover_do_inode_trans( | |||
2376 | /* do nothing */ | 2390 | /* do nothing */ |
2377 | } else { | 2391 | } else { |
2378 | xfs_buf_relse(bp); | 2392 | xfs_buf_relse(bp); |
2379 | return 0; | 2393 | error = 0; |
2394 | goto error; | ||
2380 | } | 2395 | } |
2381 | } | 2396 | } |
2382 | /* Take the opportunity to reset the flush iteration count */ | 2397 | /* Take the opportunity to reset the flush iteration count */ |
@@ -2391,7 +2406,8 @@ xlog_recover_do_inode_trans( | |||
2391 | xfs_fs_cmn_err(CE_ALERT, mp, | 2406 | xfs_fs_cmn_err(CE_ALERT, mp, |
2392 | "xfs_inode_recover: Bad regular inode log record, rec ptr 0x%p, ino ptr = 0x%p, ino bp = 0x%p, ino %Ld", | 2407 | "xfs_inode_recover: Bad regular inode log record, rec ptr 0x%p, ino ptr = 0x%p, ino bp = 0x%p, ino %Ld", |
2393 | item, dip, bp, ino); | 2408 | item, dip, bp, ino); |
2394 | return XFS_ERROR(EFSCORRUPTED); | 2409 | error = EFSCORRUPTED; |
2410 | goto error; | ||
2395 | } | 2411 | } |
2396 | } else if (unlikely((dicp->di_mode & S_IFMT) == S_IFDIR)) { | 2412 | } else if (unlikely((dicp->di_mode & S_IFMT) == S_IFDIR)) { |
2397 | if ((dicp->di_format != XFS_DINODE_FMT_EXTENTS) && | 2413 | if ((dicp->di_format != XFS_DINODE_FMT_EXTENTS) && |
@@ -2403,7 +2419,8 @@ xlog_recover_do_inode_trans( | |||
2403 | xfs_fs_cmn_err(CE_ALERT, mp, | 2419 | xfs_fs_cmn_err(CE_ALERT, mp, |
2404 | "xfs_inode_recover: Bad dir inode log record, rec ptr 0x%p, ino ptr = 0x%p, ino bp = 0x%p, ino %Ld", | 2420 | "xfs_inode_recover: Bad dir inode log record, rec ptr 0x%p, ino ptr = 0x%p, ino bp = 0x%p, ino %Ld", |
2405 | item, dip, bp, ino); | 2421 | item, dip, bp, ino); |
2406 | return XFS_ERROR(EFSCORRUPTED); | 2422 | error = EFSCORRUPTED; |
2423 | goto error; | ||
2407 | } | 2424 | } |
2408 | } | 2425 | } |
2409 | if (unlikely(dicp->di_nextents + dicp->di_anextents > dicp->di_nblocks)){ | 2426 | if (unlikely(dicp->di_nextents + dicp->di_anextents > dicp->di_nblocks)){ |
@@ -2415,7 +2432,8 @@ xlog_recover_do_inode_trans( | |||
2415 | item, dip, bp, ino, | 2432 | item, dip, bp, ino, |
2416 | dicp->di_nextents + dicp->di_anextents, | 2433 | dicp->di_nextents + dicp->di_anextents, |
2417 | dicp->di_nblocks); | 2434 | dicp->di_nblocks); |
2418 | return XFS_ERROR(EFSCORRUPTED); | 2435 | error = EFSCORRUPTED; |
2436 | goto error; | ||
2419 | } | 2437 | } |
2420 | if (unlikely(dicp->di_forkoff > mp->m_sb.sb_inodesize)) { | 2438 | if (unlikely(dicp->di_forkoff > mp->m_sb.sb_inodesize)) { |
2421 | XFS_CORRUPTION_ERROR("xlog_recover_do_inode_trans(6)", | 2439 | XFS_CORRUPTION_ERROR("xlog_recover_do_inode_trans(6)", |
@@ -2424,7 +2442,8 @@ xlog_recover_do_inode_trans( | |||
2424 | xfs_fs_cmn_err(CE_ALERT, mp, | 2442 | xfs_fs_cmn_err(CE_ALERT, mp, |
2425 | "xfs_inode_recover: Bad inode log rec ptr 0x%p, dino ptr 0x%p, dino bp 0x%p, ino %Ld, forkoff 0x%x", | 2443 | "xfs_inode_recover: Bad inode log rec ptr 0x%p, dino ptr 0x%p, dino bp 0x%p, ino %Ld, forkoff 0x%x", |
2426 | item, dip, bp, ino, dicp->di_forkoff); | 2444 | item, dip, bp, ino, dicp->di_forkoff); |
2427 | return XFS_ERROR(EFSCORRUPTED); | 2445 | error = EFSCORRUPTED; |
2446 | goto error; | ||
2428 | } | 2447 | } |
2429 | if (unlikely(item->ri_buf[1].i_len > sizeof(xfs_dinode_core_t))) { | 2448 | if (unlikely(item->ri_buf[1].i_len > sizeof(xfs_dinode_core_t))) { |
2430 | XFS_CORRUPTION_ERROR("xlog_recover_do_inode_trans(7)", | 2449 | XFS_CORRUPTION_ERROR("xlog_recover_do_inode_trans(7)", |
@@ -2433,7 +2452,8 @@ xlog_recover_do_inode_trans( | |||
2433 | xfs_fs_cmn_err(CE_ALERT, mp, | 2452 | xfs_fs_cmn_err(CE_ALERT, mp, |
2434 | "xfs_inode_recover: Bad inode log record length %d, rec ptr 0x%p", | 2453 | "xfs_inode_recover: Bad inode log record length %d, rec ptr 0x%p", |
2435 | item->ri_buf[1].i_len, item); | 2454 | item->ri_buf[1].i_len, item); |
2436 | return XFS_ERROR(EFSCORRUPTED); | 2455 | error = EFSCORRUPTED; |
2456 | goto error; | ||
2437 | } | 2457 | } |
2438 | 2458 | ||
2439 | /* The core is in in-core format */ | 2459 | /* The core is in in-core format */ |
@@ -2521,7 +2541,8 @@ xlog_recover_do_inode_trans( | |||
2521 | xlog_warn("XFS: xlog_recover_do_inode_trans: Invalid flag"); | 2541 | xlog_warn("XFS: xlog_recover_do_inode_trans: Invalid flag"); |
2522 | ASSERT(0); | 2542 | ASSERT(0); |
2523 | xfs_buf_relse(bp); | 2543 | xfs_buf_relse(bp); |
2524 | return XFS_ERROR(EIO); | 2544 | error = EIO; |
2545 | goto error; | ||
2525 | } | 2546 | } |
2526 | } | 2547 | } |
2527 | 2548 | ||
@@ -2537,7 +2558,10 @@ write_inode_buffer: | |||
2537 | error = xfs_bwrite(mp, bp); | 2558 | error = xfs_bwrite(mp, bp); |
2538 | } | 2559 | } |
2539 | 2560 | ||
2540 | return (error); | 2561 | error: |
2562 | if (need_free) | ||
2563 | kmem_free(in_f, sizeof(*in_f)); | ||
2564 | return XFS_ERROR(error); | ||
2541 | } | 2565 | } |
2542 | 2566 | ||
2543 | /* | 2567 | /* |
@@ -2674,32 +2698,32 @@ xlog_recover_do_dquot_trans( | |||
2674 | * structure into it, and adds the efi to the AIL with the given | 2698 | * structure into it, and adds the efi to the AIL with the given |
2675 | * LSN. | 2699 | * LSN. |
2676 | */ | 2700 | */ |
2677 | STATIC void | 2701 | STATIC int |
2678 | xlog_recover_do_efi_trans( | 2702 | xlog_recover_do_efi_trans( |
2679 | xlog_t *log, | 2703 | xlog_t *log, |
2680 | xlog_recover_item_t *item, | 2704 | xlog_recover_item_t *item, |
2681 | xfs_lsn_t lsn, | 2705 | xfs_lsn_t lsn, |
2682 | int pass) | 2706 | int pass) |
2683 | { | 2707 | { |
2708 | int error; | ||
2684 | xfs_mount_t *mp; | 2709 | xfs_mount_t *mp; |
2685 | xfs_efi_log_item_t *efip; | 2710 | xfs_efi_log_item_t *efip; |
2686 | xfs_efi_log_format_t *efi_formatp; | 2711 | xfs_efi_log_format_t *efi_formatp; |
2687 | SPLDECL(s); | 2712 | SPLDECL(s); |
2688 | 2713 | ||
2689 | if (pass == XLOG_RECOVER_PASS1) { | 2714 | if (pass == XLOG_RECOVER_PASS1) { |
2690 | return; | 2715 | return 0; |
2691 | } | 2716 | } |
2692 | 2717 | ||
2693 | efi_formatp = (xfs_efi_log_format_t *)item->ri_buf[0].i_addr; | 2718 | efi_formatp = (xfs_efi_log_format_t *)item->ri_buf[0].i_addr; |
2694 | ASSERT(item->ri_buf[0].i_len == | ||
2695 | (sizeof(xfs_efi_log_format_t) + | ||
2696 | ((efi_formatp->efi_nextents - 1) * sizeof(xfs_extent_t)))); | ||
2697 | 2719 | ||
2698 | mp = log->l_mp; | 2720 | mp = log->l_mp; |
2699 | efip = xfs_efi_init(mp, efi_formatp->efi_nextents); | 2721 | efip = xfs_efi_init(mp, efi_formatp->efi_nextents); |
2700 | memcpy((char *)&(efip->efi_format), (char *)efi_formatp, | 2722 | if ((error = xfs_efi_copy_format(&(item->ri_buf[0]), |
2701 | sizeof(xfs_efi_log_format_t) + | 2723 | &(efip->efi_format)))) { |
2702 | ((efi_formatp->efi_nextents - 1) * sizeof(xfs_extent_t))); | 2724 | xfs_efi_item_free(efip); |
2725 | return error; | ||
2726 | } | ||
2703 | efip->efi_next_extent = efi_formatp->efi_nextents; | 2727 | efip->efi_next_extent = efi_formatp->efi_nextents; |
2704 | efip->efi_flags |= XFS_EFI_COMMITTED; | 2728 | efip->efi_flags |= XFS_EFI_COMMITTED; |
2705 | 2729 | ||
@@ -2708,6 +2732,7 @@ xlog_recover_do_efi_trans( | |||
2708 | * xfs_trans_update_ail() drops the AIL lock. | 2732 | * xfs_trans_update_ail() drops the AIL lock. |
2709 | */ | 2733 | */ |
2710 | xfs_trans_update_ail(mp, (xfs_log_item_t *)efip, lsn, s); | 2734 | xfs_trans_update_ail(mp, (xfs_log_item_t *)efip, lsn, s); |
2735 | return 0; | ||
2711 | } | 2736 | } |
2712 | 2737 | ||
2713 | 2738 | ||
@@ -2738,9 +2763,10 @@ xlog_recover_do_efd_trans( | |||
2738 | } | 2763 | } |
2739 | 2764 | ||
2740 | efd_formatp = (xfs_efd_log_format_t *)item->ri_buf[0].i_addr; | 2765 | efd_formatp = (xfs_efd_log_format_t *)item->ri_buf[0].i_addr; |
2741 | ASSERT(item->ri_buf[0].i_len == | 2766 | ASSERT((item->ri_buf[0].i_len == (sizeof(xfs_efd_log_format_32_t) + |
2742 | (sizeof(xfs_efd_log_format_t) + | 2767 | ((efd_formatp->efd_nextents - 1) * sizeof(xfs_extent_32_t)))) || |
2743 | ((efd_formatp->efd_nextents - 1) * sizeof(xfs_extent_t)))); | 2768 | (item->ri_buf[0].i_len == (sizeof(xfs_efd_log_format_64_t) + |
2769 | ((efd_formatp->efd_nextents - 1) * sizeof(xfs_extent_64_t))))); | ||
2744 | efi_id = efd_formatp->efd_efi_id; | 2770 | efi_id = efd_formatp->efd_efi_id; |
2745 | 2771 | ||
2746 | /* | 2772 | /* |
@@ -2810,15 +2836,14 @@ xlog_recover_do_trans( | |||
2810 | if ((error = xlog_recover_do_buffer_trans(log, item, | 2836 | if ((error = xlog_recover_do_buffer_trans(log, item, |
2811 | pass))) | 2837 | pass))) |
2812 | break; | 2838 | break; |
2813 | } else if ((ITEM_TYPE(item) == XFS_LI_INODE) || | 2839 | } else if ((ITEM_TYPE(item) == XFS_LI_INODE)) { |
2814 | (ITEM_TYPE(item) == XFS_LI_6_1_INODE) || | ||
2815 | (ITEM_TYPE(item) == XFS_LI_5_3_INODE)) { | ||
2816 | if ((error = xlog_recover_do_inode_trans(log, item, | 2840 | if ((error = xlog_recover_do_inode_trans(log, item, |
2817 | pass))) | 2841 | pass))) |
2818 | break; | 2842 | break; |
2819 | } else if (ITEM_TYPE(item) == XFS_LI_EFI) { | 2843 | } else if (ITEM_TYPE(item) == XFS_LI_EFI) { |
2820 | xlog_recover_do_efi_trans(log, item, trans->r_lsn, | 2844 | if ((error = xlog_recover_do_efi_trans(log, item, trans->r_lsn, |
2821 | pass); | 2845 | pass))) |
2846 | break; | ||
2822 | } else if (ITEM_TYPE(item) == XFS_LI_EFD) { | 2847 | } else if (ITEM_TYPE(item) == XFS_LI_EFD) { |
2823 | xlog_recover_do_efd_trans(log, item, pass); | 2848 | xlog_recover_do_efd_trans(log, item, pass); |
2824 | } else if (ITEM_TYPE(item) == XFS_LI_DQUOT) { | 2849 | } else if (ITEM_TYPE(item) == XFS_LI_DQUOT) { |
@@ -3798,7 +3823,7 @@ xlog_do_log_recovery( | |||
3798 | error = xlog_do_recovery_pass(log, head_blk, tail_blk, | 3823 | error = xlog_do_recovery_pass(log, head_blk, tail_blk, |
3799 | XLOG_RECOVER_PASS2); | 3824 | XLOG_RECOVER_PASS2); |
3800 | #ifdef DEBUG | 3825 | #ifdef DEBUG |
3801 | { | 3826 | if (!error) { |
3802 | int i; | 3827 | int i; |
3803 | 3828 | ||
3804 | for (i = 0; i < XLOG_BC_TABLE_SIZE; i++) | 3829 | for (i = 0; i < XLOG_BC_TABLE_SIZE; i++) |