diff options
Diffstat (limited to 'fs/xfs/xfs_btree.c')
-rw-r--r-- | fs/xfs/xfs_btree.c | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/fs/xfs/xfs_btree.c b/fs/xfs/xfs_btree.c index 8de884c4dab7..3b6e01dea669 100644 --- a/fs/xfs/xfs_btree.c +++ b/fs/xfs/xfs_btree.c | |||
@@ -2469,6 +2469,107 @@ error0: | |||
2469 | } | 2469 | } |
2470 | 2470 | ||
2471 | /* | 2471 | /* |
2472 | * Copy the old inode root contents into a real block and make the | ||
2473 | * broot point to it. | ||
2474 | */ | ||
2475 | int /* error */ | ||
2476 | xfs_btree_new_iroot( | ||
2477 | struct xfs_btree_cur *cur, /* btree cursor */ | ||
2478 | int *logflags, /* logging flags for inode */ | ||
2479 | int *stat) /* return status - 0 fail */ | ||
2480 | { | ||
2481 | struct xfs_buf *cbp; /* buffer for cblock */ | ||
2482 | struct xfs_btree_block *block; /* btree block */ | ||
2483 | struct xfs_btree_block *cblock; /* child btree block */ | ||
2484 | union xfs_btree_key *ckp; /* child key pointer */ | ||
2485 | union xfs_btree_ptr *cpp; /* child ptr pointer */ | ||
2486 | union xfs_btree_key *kp; /* pointer to btree key */ | ||
2487 | union xfs_btree_ptr *pp; /* pointer to block addr */ | ||
2488 | union xfs_btree_ptr nptr; /* new block addr */ | ||
2489 | int level; /* btree level */ | ||
2490 | int error; /* error return code */ | ||
2491 | #ifdef DEBUG | ||
2492 | int i; /* loop counter */ | ||
2493 | #endif | ||
2494 | |||
2495 | XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); | ||
2496 | XFS_BTREE_STATS_INC(cur, newroot); | ||
2497 | |||
2498 | ASSERT(cur->bc_flags & XFS_BTREE_ROOT_IN_INODE); | ||
2499 | |||
2500 | level = cur->bc_nlevels - 1; | ||
2501 | |||
2502 | block = xfs_btree_get_iroot(cur); | ||
2503 | pp = xfs_btree_ptr_addr(cur, 1, block); | ||
2504 | |||
2505 | /* Allocate the new block. If we can't do it, we're toast. Give up. */ | ||
2506 | error = cur->bc_ops->alloc_block(cur, pp, &nptr, 1, stat); | ||
2507 | if (error) | ||
2508 | goto error0; | ||
2509 | if (*stat == 0) { | ||
2510 | XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); | ||
2511 | return 0; | ||
2512 | } | ||
2513 | XFS_BTREE_STATS_INC(cur, alloc); | ||
2514 | |||
2515 | /* Copy the root into a real block. */ | ||
2516 | error = xfs_btree_get_buf_block(cur, &nptr, 0, &cblock, &cbp); | ||
2517 | if (error) | ||
2518 | goto error0; | ||
2519 | |||
2520 | memcpy(cblock, block, xfs_btree_block_len(cur)); | ||
2521 | |||
2522 | be16_add_cpu(&block->bb_level, 1); | ||
2523 | xfs_btree_set_numrecs(block, 1); | ||
2524 | cur->bc_nlevels++; | ||
2525 | cur->bc_ptrs[level + 1] = 1; | ||
2526 | |||
2527 | kp = xfs_btree_key_addr(cur, 1, block); | ||
2528 | ckp = xfs_btree_key_addr(cur, 1, cblock); | ||
2529 | xfs_btree_copy_keys(cur, ckp, kp, xfs_btree_get_numrecs(cblock)); | ||
2530 | |||
2531 | cpp = xfs_btree_ptr_addr(cur, 1, cblock); | ||
2532 | #ifdef DEBUG | ||
2533 | for (i = 0; i < be16_to_cpu(cblock->bb_numrecs); i++) { | ||
2534 | error = xfs_btree_check_ptr(cur, pp, i, level); | ||
2535 | if (error) | ||
2536 | goto error0; | ||
2537 | } | ||
2538 | #endif | ||
2539 | xfs_btree_copy_ptrs(cur, cpp, pp, xfs_btree_get_numrecs(cblock)); | ||
2540 | |||
2541 | #ifdef DEBUG | ||
2542 | error = xfs_btree_check_ptr(cur, &nptr, 0, level); | ||
2543 | if (error) | ||
2544 | goto error0; | ||
2545 | #endif | ||
2546 | xfs_btree_copy_ptrs(cur, pp, &nptr, 1); | ||
2547 | |||
2548 | xfs_iroot_realloc(cur->bc_private.b.ip, | ||
2549 | 1 - xfs_btree_get_numrecs(cblock), | ||
2550 | cur->bc_private.b.whichfork); | ||
2551 | |||
2552 | xfs_btree_setbuf(cur, level, cbp); | ||
2553 | |||
2554 | /* | ||
2555 | * Do all this logging at the end so that | ||
2556 | * the root is at the right level. | ||
2557 | */ | ||
2558 | xfs_btree_log_block(cur, cbp, XFS_BB_ALL_BITS); | ||
2559 | xfs_btree_log_keys(cur, cbp, 1, be16_to_cpu(cblock->bb_numrecs)); | ||
2560 | xfs_btree_log_ptrs(cur, cbp, 1, be16_to_cpu(cblock->bb_numrecs)); | ||
2561 | |||
2562 | *logflags |= | ||
2563 | XFS_ILOG_CORE | XFS_ILOG_FBROOT(cur->bc_private.b.whichfork); | ||
2564 | *stat = 1; | ||
2565 | XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); | ||
2566 | return 0; | ||
2567 | error0: | ||
2568 | XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR); | ||
2569 | return error; | ||
2570 | } | ||
2571 | |||
2572 | /* | ||
2472 | * Allocate a new root block, fill it in. | 2573 | * Allocate a new root block, fill it in. |
2473 | */ | 2574 | */ |
2474 | int /* error */ | 2575 | int /* error */ |