aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_log_recover.c
diff options
context:
space:
mode:
authorTim Shimmin <tes@sgi.com>2006-06-09 00:55:38 -0400
committerNathan Scott <nathans@sgi.com>2006-06-09 00:55:38 -0400
commit6d192a9b82212abf1e0e89da6e3a952afba7e4d6 (patch)
tree608a463ba4fd04f518558ead3567952e757cd2ae /fs/xfs/xfs_log_recover.c
parentd210a28cd851082cec9b282443f8cc0e6fc09830 (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.c87
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); 2561error:
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 */
2677STATIC void 2701STATIC int
2678xlog_recover_do_efi_trans( 2702xlog_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++)