diff options
author | Christoph Hellwig <hch@infradead.org> | 2008-10-30 01:57:16 -0400 |
---|---|---|
committer | Lachlan McIlroy <lachlan@sgi.com> | 2008-10-30 01:57:16 -0400 |
commit | 344207ce8474b79be331eb93e6df4cb5bdd48ab2 (patch) | |
tree | 7858f63c359e2695a6c368a73b078ff183345922 | |
parent | f5eb8e7ca58bc1e92436614444006120d21668ba (diff) |
[XFS] implement semi-generic xfs_btree_new_root
From: Dave Chinner <dgc@sgi.com>
Add a xfs_btree_new_root helper for the alloc and ialloc btrees. The bmap
btree needs it's own version and is not converted.
[hch: split out from bigger patch and minor adaptions]
SGI-PV: 985583
SGI-Modid: xfs-linux-melb:xfs-kern:32200a
Signed-off-by: Christoph Hellwig <hch@infradead.org>
Signed-off-by: Lachlan McIlroy <lachlan@sgi.com>
Signed-off-by: Bill O'Donnell <billodo@sgi.com>
Signed-off-by: David Chinner <david@fromorbit.com>
-rw-r--r-- | fs/xfs/xfs_alloc_btree.c | 179 | ||||
-rw-r--r-- | fs/xfs/xfs_btree.c | 129 | ||||
-rw-r--r-- | fs/xfs/xfs_btree.h | 5 | ||||
-rw-r--r-- | fs/xfs/xfs_ialloc_btree.c | 164 |
4 files changed, 172 insertions, 305 deletions
diff --git a/fs/xfs/xfs_alloc_btree.c b/fs/xfs/xfs_alloc_btree.c index 8a8d1aeec52a..f21a3e9cc3db 100644 --- a/fs/xfs/xfs_alloc_btree.c +++ b/fs/xfs/xfs_alloc_btree.c | |||
@@ -48,7 +48,6 @@ STATIC void xfs_alloc_log_block(xfs_trans_t *, xfs_buf_t *, int); | |||
48 | STATIC void xfs_alloc_log_keys(xfs_btree_cur_t *, xfs_buf_t *, int, int); | 48 | STATIC void xfs_alloc_log_keys(xfs_btree_cur_t *, xfs_buf_t *, int, int); |
49 | STATIC void xfs_alloc_log_ptrs(xfs_btree_cur_t *, xfs_buf_t *, int, int); | 49 | STATIC void xfs_alloc_log_ptrs(xfs_btree_cur_t *, xfs_buf_t *, int, int); |
50 | STATIC void xfs_alloc_log_recs(xfs_btree_cur_t *, xfs_buf_t *, int, int); | 50 | STATIC void xfs_alloc_log_recs(xfs_btree_cur_t *, xfs_buf_t *, int, int); |
51 | STATIC int xfs_alloc_newroot(xfs_btree_cur_t *, int *); | ||
52 | 51 | ||
53 | /* | 52 | /* |
54 | * Internal functions. | 53 | * Internal functions. |
@@ -628,7 +627,7 @@ xfs_alloc_insrec( | |||
628 | */ | 627 | */ |
629 | if (level >= cur->bc_nlevels) { | 628 | if (level >= cur->bc_nlevels) { |
630 | XFS_STATS_INC(xs_abt_insrec); | 629 | XFS_STATS_INC(xs_abt_insrec); |
631 | if ((error = xfs_alloc_newroot(cur, &i))) | 630 | if ((error = xfs_btree_new_root(cur, &i))) |
632 | return error; | 631 | return error; |
633 | *bnop = NULLAGBLOCK; | 632 | *bnop = NULLAGBLOCK; |
634 | *stat = i; | 633 | *stat = i; |
@@ -936,161 +935,6 @@ xfs_alloc_log_recs( | |||
936 | xfs_trans_log_buf(cur->bc_tp, bp, first, last); | 935 | xfs_trans_log_buf(cur->bc_tp, bp, first, last); |
937 | } | 936 | } |
938 | 937 | ||
939 | /* | ||
940 | * Allocate a new root block, fill it in. | ||
941 | */ | ||
942 | STATIC int /* error */ | ||
943 | xfs_alloc_newroot( | ||
944 | xfs_btree_cur_t *cur, /* btree cursor */ | ||
945 | int *stat) /* success/failure */ | ||
946 | { | ||
947 | int error; /* error return value */ | ||
948 | xfs_agblock_t lbno; /* left block number */ | ||
949 | xfs_buf_t *lbp; /* left btree buffer */ | ||
950 | xfs_alloc_block_t *left; /* left btree block */ | ||
951 | xfs_mount_t *mp; /* mount structure */ | ||
952 | xfs_agblock_t nbno; /* new block number */ | ||
953 | xfs_buf_t *nbp; /* new (root) buffer */ | ||
954 | xfs_alloc_block_t *new; /* new (root) btree block */ | ||
955 | int nptr; /* new value for key index, 1 or 2 */ | ||
956 | xfs_agblock_t rbno; /* right block number */ | ||
957 | xfs_buf_t *rbp; /* right btree buffer */ | ||
958 | xfs_alloc_block_t *right; /* right btree block */ | ||
959 | |||
960 | mp = cur->bc_mp; | ||
961 | |||
962 | ASSERT(cur->bc_nlevels < XFS_AG_MAXLEVELS(mp)); | ||
963 | /* | ||
964 | * Get a buffer from the freelist blocks, for the new root. | ||
965 | */ | ||
966 | error = xfs_alloc_get_freelist(cur->bc_tp, | ||
967 | cur->bc_private.a.agbp, &nbno, 1); | ||
968 | if (error) | ||
969 | return error; | ||
970 | /* | ||
971 | * None available, we fail. | ||
972 | */ | ||
973 | if (nbno == NULLAGBLOCK) { | ||
974 | *stat = 0; | ||
975 | return 0; | ||
976 | } | ||
977 | xfs_trans_agbtree_delta(cur->bc_tp, 1); | ||
978 | nbp = xfs_btree_get_bufs(mp, cur->bc_tp, cur->bc_private.a.agno, nbno, | ||
979 | 0); | ||
980 | new = XFS_BUF_TO_ALLOC_BLOCK(nbp); | ||
981 | /* | ||
982 | * Set the root data in the a.g. freespace structure. | ||
983 | */ | ||
984 | { | ||
985 | xfs_agf_t *agf; /* a.g. freespace header */ | ||
986 | xfs_agnumber_t seqno; | ||
987 | |||
988 | agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp); | ||
989 | agf->agf_roots[cur->bc_btnum] = cpu_to_be32(nbno); | ||
990 | be32_add_cpu(&agf->agf_levels[cur->bc_btnum], 1); | ||
991 | seqno = be32_to_cpu(agf->agf_seqno); | ||
992 | mp->m_perag[seqno].pagf_levels[cur->bc_btnum]++; | ||
993 | xfs_alloc_log_agf(cur->bc_tp, cur->bc_private.a.agbp, | ||
994 | XFS_AGF_ROOTS | XFS_AGF_LEVELS); | ||
995 | } | ||
996 | /* | ||
997 | * At the previous root level there are now two blocks: the old | ||
998 | * root, and the new block generated when it was split. | ||
999 | * We don't know which one the cursor is pointing at, so we | ||
1000 | * set up variables "left" and "right" for each case. | ||
1001 | */ | ||
1002 | lbp = cur->bc_bufs[cur->bc_nlevels - 1]; | ||
1003 | left = XFS_BUF_TO_ALLOC_BLOCK(lbp); | ||
1004 | #ifdef DEBUG | ||
1005 | if ((error = xfs_btree_check_sblock(cur, left, cur->bc_nlevels - 1, lbp))) | ||
1006 | return error; | ||
1007 | #endif | ||
1008 | if (be32_to_cpu(left->bb_rightsib) != NULLAGBLOCK) { | ||
1009 | /* | ||
1010 | * Our block is left, pick up the right block. | ||
1011 | */ | ||
1012 | lbno = XFS_DADDR_TO_AGBNO(mp, XFS_BUF_ADDR(lbp)); | ||
1013 | rbno = be32_to_cpu(left->bb_rightsib); | ||
1014 | if ((error = xfs_btree_read_bufs(mp, cur->bc_tp, | ||
1015 | cur->bc_private.a.agno, rbno, 0, &rbp, | ||
1016 | XFS_ALLOC_BTREE_REF))) | ||
1017 | return error; | ||
1018 | right = XFS_BUF_TO_ALLOC_BLOCK(rbp); | ||
1019 | if ((error = xfs_btree_check_sblock(cur, right, | ||
1020 | cur->bc_nlevels - 1, rbp))) | ||
1021 | return error; | ||
1022 | nptr = 1; | ||
1023 | } else { | ||
1024 | /* | ||
1025 | * Our block is right, pick up the left block. | ||
1026 | */ | ||
1027 | rbp = lbp; | ||
1028 | right = left; | ||
1029 | rbno = XFS_DADDR_TO_AGBNO(mp, XFS_BUF_ADDR(rbp)); | ||
1030 | lbno = be32_to_cpu(right->bb_leftsib); | ||
1031 | if ((error = xfs_btree_read_bufs(mp, cur->bc_tp, | ||
1032 | cur->bc_private.a.agno, lbno, 0, &lbp, | ||
1033 | XFS_ALLOC_BTREE_REF))) | ||
1034 | return error; | ||
1035 | left = XFS_BUF_TO_ALLOC_BLOCK(lbp); | ||
1036 | if ((error = xfs_btree_check_sblock(cur, left, | ||
1037 | cur->bc_nlevels - 1, lbp))) | ||
1038 | return error; | ||
1039 | nptr = 2; | ||
1040 | } | ||
1041 | /* | ||
1042 | * Fill in the new block's btree header and log it. | ||
1043 | */ | ||
1044 | new->bb_magic = cpu_to_be32(xfs_magics[cur->bc_btnum]); | ||
1045 | new->bb_level = cpu_to_be16(cur->bc_nlevels); | ||
1046 | new->bb_numrecs = cpu_to_be16(2); | ||
1047 | new->bb_leftsib = cpu_to_be32(NULLAGBLOCK); | ||
1048 | new->bb_rightsib = cpu_to_be32(NULLAGBLOCK); | ||
1049 | xfs_alloc_log_block(cur->bc_tp, nbp, XFS_BB_ALL_BITS); | ||
1050 | ASSERT(lbno != NULLAGBLOCK && rbno != NULLAGBLOCK); | ||
1051 | /* | ||
1052 | * Fill in the key data in the new root. | ||
1053 | */ | ||
1054 | { | ||
1055 | xfs_alloc_key_t *kp; /* btree key pointer */ | ||
1056 | |||
1057 | kp = XFS_ALLOC_KEY_ADDR(new, 1, cur); | ||
1058 | if (be16_to_cpu(left->bb_level) > 0) { | ||
1059 | kp[0] = *XFS_ALLOC_KEY_ADDR(left, 1, cur); | ||
1060 | kp[1] = *XFS_ALLOC_KEY_ADDR(right, 1, cur); | ||
1061 | } else { | ||
1062 | xfs_alloc_rec_t *rp; /* btree record pointer */ | ||
1063 | |||
1064 | rp = XFS_ALLOC_REC_ADDR(left, 1, cur); | ||
1065 | kp[0].ar_startblock = rp->ar_startblock; | ||
1066 | kp[0].ar_blockcount = rp->ar_blockcount; | ||
1067 | rp = XFS_ALLOC_REC_ADDR(right, 1, cur); | ||
1068 | kp[1].ar_startblock = rp->ar_startblock; | ||
1069 | kp[1].ar_blockcount = rp->ar_blockcount; | ||
1070 | } | ||
1071 | } | ||
1072 | xfs_alloc_log_keys(cur, nbp, 1, 2); | ||
1073 | /* | ||
1074 | * Fill in the pointer data in the new root. | ||
1075 | */ | ||
1076 | { | ||
1077 | xfs_alloc_ptr_t *pp; /* btree address pointer */ | ||
1078 | |||
1079 | pp = XFS_ALLOC_PTR_ADDR(new, 1, cur); | ||
1080 | pp[0] = cpu_to_be32(lbno); | ||
1081 | pp[1] = cpu_to_be32(rbno); | ||
1082 | } | ||
1083 | xfs_alloc_log_ptrs(cur, nbp, 1, 2); | ||
1084 | /* | ||
1085 | * Fix up the cursor. | ||
1086 | */ | ||
1087 | xfs_btree_setbuf(cur, cur->bc_nlevels, nbp); | ||
1088 | cur->bc_ptrs[cur->bc_nlevels] = nptr; | ||
1089 | cur->bc_nlevels++; | ||
1090 | *stat = 1; | ||
1091 | return 0; | ||
1092 | } | ||
1093 | |||
1094 | 938 | ||
1095 | /* | 939 | /* |
1096 | * Externally visible routines. | 940 | * Externally visible routines. |
@@ -1244,6 +1088,26 @@ xfs_allocbt_dup_cursor( | |||
1244 | cur->bc_btnum); | 1088 | cur->bc_btnum); |
1245 | } | 1089 | } |
1246 | 1090 | ||
1091 | STATIC void | ||
1092 | xfs_allocbt_set_root( | ||
1093 | struct xfs_btree_cur *cur, | ||
1094 | union xfs_btree_ptr *ptr, | ||
1095 | int inc) | ||
1096 | { | ||
1097 | struct xfs_buf *agbp = cur->bc_private.a.agbp; | ||
1098 | struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp); | ||
1099 | xfs_agnumber_t seqno = be32_to_cpu(agf->agf_seqno); | ||
1100 | int btnum = cur->bc_btnum; | ||
1101 | |||
1102 | ASSERT(ptr->s != 0); | ||
1103 | |||
1104 | agf->agf_roots[btnum] = ptr->s; | ||
1105 | be32_add_cpu(&agf->agf_levels[btnum], inc); | ||
1106 | cur->bc_mp->m_perag[seqno].pagf_levels[btnum] += inc; | ||
1107 | |||
1108 | xfs_alloc_log_agf(cur->bc_tp, agbp, XFS_AGF_ROOTS | XFS_AGF_LEVELS); | ||
1109 | } | ||
1110 | |||
1247 | STATIC int | 1111 | STATIC int |
1248 | xfs_allocbt_alloc_block( | 1112 | xfs_allocbt_alloc_block( |
1249 | struct xfs_btree_cur *cur, | 1113 | struct xfs_btree_cur *cur, |
@@ -1440,6 +1304,7 @@ static const struct xfs_btree_ops xfs_allocbt_ops = { | |||
1440 | .key_len = sizeof(xfs_alloc_key_t), | 1304 | .key_len = sizeof(xfs_alloc_key_t), |
1441 | 1305 | ||
1442 | .dup_cursor = xfs_allocbt_dup_cursor, | 1306 | .dup_cursor = xfs_allocbt_dup_cursor, |
1307 | .set_root = xfs_allocbt_set_root, | ||
1443 | .alloc_block = xfs_allocbt_alloc_block, | 1308 | .alloc_block = xfs_allocbt_alloc_block, |
1444 | .update_lastrec = xfs_allocbt_update_lastrec, | 1309 | .update_lastrec = xfs_allocbt_update_lastrec, |
1445 | .get_maxrecs = xfs_allocbt_get_maxrecs, | 1310 | .get_maxrecs = xfs_allocbt_get_maxrecs, |
diff --git a/fs/xfs/xfs_btree.c b/fs/xfs/xfs_btree.c index 80576695fbe5..8de884c4dab7 100644 --- a/fs/xfs/xfs_btree.c +++ b/fs/xfs/xfs_btree.c | |||
@@ -2467,3 +2467,132 @@ error0: | |||
2467 | XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR); | 2467 | XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR); |
2468 | return error; | 2468 | return error; |
2469 | } | 2469 | } |
2470 | |||
2471 | /* | ||
2472 | * Allocate a new root block, fill it in. | ||
2473 | */ | ||
2474 | int /* error */ | ||
2475 | xfs_btree_new_root( | ||
2476 | struct xfs_btree_cur *cur, /* btree cursor */ | ||
2477 | int *stat) /* success/failure */ | ||
2478 | { | ||
2479 | struct xfs_btree_block *block; /* one half of the old root block */ | ||
2480 | struct xfs_buf *bp; /* buffer containing block */ | ||
2481 | int error; /* error return value */ | ||
2482 | struct xfs_buf *lbp; /* left buffer pointer */ | ||
2483 | struct xfs_btree_block *left; /* left btree block */ | ||
2484 | struct xfs_buf *nbp; /* new (root) buffer */ | ||
2485 | struct xfs_btree_block *new; /* new (root) btree block */ | ||
2486 | int nptr; /* new value for key index, 1 or 2 */ | ||
2487 | struct xfs_buf *rbp; /* right buffer pointer */ | ||
2488 | struct xfs_btree_block *right; /* right btree block */ | ||
2489 | union xfs_btree_ptr rptr; | ||
2490 | union xfs_btree_ptr lptr; | ||
2491 | |||
2492 | XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); | ||
2493 | XFS_BTREE_STATS_INC(cur, newroot); | ||
2494 | |||
2495 | /* initialise our start point from the cursor */ | ||
2496 | cur->bc_ops->init_ptr_from_cur(cur, &rptr); | ||
2497 | |||
2498 | /* Allocate the new block. If we can't do it, we're toast. Give up. */ | ||
2499 | error = cur->bc_ops->alloc_block(cur, &rptr, &lptr, 1, stat); | ||
2500 | if (error) | ||
2501 | goto error0; | ||
2502 | if (*stat == 0) | ||
2503 | goto out0; | ||
2504 | XFS_BTREE_STATS_INC(cur, alloc); | ||
2505 | |||
2506 | /* Set up the new block. */ | ||
2507 | error = xfs_btree_get_buf_block(cur, &lptr, 0, &new, &nbp); | ||
2508 | if (error) | ||
2509 | goto error0; | ||
2510 | |||
2511 | /* Set the root in the holding structure increasing the level by 1. */ | ||
2512 | cur->bc_ops->set_root(cur, &lptr, 1); | ||
2513 | |||
2514 | /* | ||
2515 | * At the previous root level there are now two blocks: the old root, | ||
2516 | * and the new block generated when it was split. We don't know which | ||
2517 | * one the cursor is pointing at, so we set up variables "left" and | ||
2518 | * "right" for each case. | ||
2519 | */ | ||
2520 | block = xfs_btree_get_block(cur, cur->bc_nlevels - 1, &bp); | ||
2521 | |||
2522 | #ifdef DEBUG | ||
2523 | error = xfs_btree_check_block(cur, block, cur->bc_nlevels - 1, bp); | ||
2524 | if (error) | ||
2525 | goto error0; | ||
2526 | #endif | ||
2527 | |||
2528 | xfs_btree_get_sibling(cur, block, &rptr, XFS_BB_RIGHTSIB); | ||
2529 | if (!xfs_btree_ptr_is_null(cur, &rptr)) { | ||
2530 | /* Our block is left, pick up the right block. */ | ||
2531 | lbp = bp; | ||
2532 | xfs_btree_buf_to_ptr(cur, lbp, &lptr); | ||
2533 | left = block; | ||
2534 | error = xfs_btree_read_buf_block(cur, &rptr, | ||
2535 | cur->bc_nlevels - 1, 0, &right, &rbp); | ||
2536 | if (error) | ||
2537 | goto error0; | ||
2538 | bp = rbp; | ||
2539 | nptr = 1; | ||
2540 | } else { | ||
2541 | /* Our block is right, pick up the left block. */ | ||
2542 | rbp = bp; | ||
2543 | xfs_btree_buf_to_ptr(cur, rbp, &rptr); | ||
2544 | right = block; | ||
2545 | xfs_btree_get_sibling(cur, right, &lptr, XFS_BB_LEFTSIB); | ||
2546 | error = xfs_btree_read_buf_block(cur, &lptr, | ||
2547 | cur->bc_nlevels - 1, 0, &left, &lbp); | ||
2548 | if (error) | ||
2549 | goto error0; | ||
2550 | bp = lbp; | ||
2551 | nptr = 2; | ||
2552 | } | ||
2553 | /* Fill in the new block's btree header and log it. */ | ||
2554 | xfs_btree_init_block(cur, cur->bc_nlevels, 2, new); | ||
2555 | xfs_btree_log_block(cur, nbp, XFS_BB_ALL_BITS); | ||
2556 | ASSERT(!xfs_btree_ptr_is_null(cur, &lptr) && | ||
2557 | !xfs_btree_ptr_is_null(cur, &rptr)); | ||
2558 | |||
2559 | /* Fill in the key data in the new root. */ | ||
2560 | if (xfs_btree_get_level(left) > 0) { | ||
2561 | xfs_btree_copy_keys(cur, | ||
2562 | xfs_btree_key_addr(cur, 1, new), | ||
2563 | xfs_btree_key_addr(cur, 1, left), 1); | ||
2564 | xfs_btree_copy_keys(cur, | ||
2565 | xfs_btree_key_addr(cur, 2, new), | ||
2566 | xfs_btree_key_addr(cur, 1, right), 1); | ||
2567 | } else { | ||
2568 | cur->bc_ops->init_key_from_rec( | ||
2569 | xfs_btree_key_addr(cur, 1, new), | ||
2570 | xfs_btree_rec_addr(cur, 1, left)); | ||
2571 | cur->bc_ops->init_key_from_rec( | ||
2572 | xfs_btree_key_addr(cur, 2, new), | ||
2573 | xfs_btree_rec_addr(cur, 1, right)); | ||
2574 | } | ||
2575 | xfs_btree_log_keys(cur, nbp, 1, 2); | ||
2576 | |||
2577 | /* Fill in the pointer data in the new root. */ | ||
2578 | xfs_btree_copy_ptrs(cur, | ||
2579 | xfs_btree_ptr_addr(cur, 1, new), &lptr, 1); | ||
2580 | xfs_btree_copy_ptrs(cur, | ||
2581 | xfs_btree_ptr_addr(cur, 2, new), &rptr, 1); | ||
2582 | xfs_btree_log_ptrs(cur, nbp, 1, 2); | ||
2583 | |||
2584 | /* Fix up the cursor. */ | ||
2585 | xfs_btree_setbuf(cur, cur->bc_nlevels, nbp); | ||
2586 | cur->bc_ptrs[cur->bc_nlevels] = nptr; | ||
2587 | cur->bc_nlevels++; | ||
2588 | XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); | ||
2589 | *stat = 1; | ||
2590 | return 0; | ||
2591 | error0: | ||
2592 | XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR); | ||
2593 | return error; | ||
2594 | out0: | ||
2595 | XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); | ||
2596 | *stat = 0; | ||
2597 | return 0; | ||
2598 | } | ||
diff --git a/fs/xfs/xfs_btree.h b/fs/xfs/xfs_btree.h index 354a6656fad5..18015392feb0 100644 --- a/fs/xfs/xfs_btree.h +++ b/fs/xfs/xfs_btree.h | |||
@@ -187,6 +187,10 @@ struct xfs_btree_ops { | |||
187 | /* cursor operations */ | 187 | /* cursor operations */ |
188 | struct xfs_btree_cur *(*dup_cursor)(struct xfs_btree_cur *); | 188 | struct xfs_btree_cur *(*dup_cursor)(struct xfs_btree_cur *); |
189 | 189 | ||
190 | /* update btree root pointer */ | ||
191 | void (*set_root)(struct xfs_btree_cur *cur, | ||
192 | union xfs_btree_ptr *nptr, int level_change); | ||
193 | |||
190 | /* block allocation / freeing */ | 194 | /* block allocation / freeing */ |
191 | int (*alloc_block)(struct xfs_btree_cur *cur, | 195 | int (*alloc_block)(struct xfs_btree_cur *cur, |
192 | union xfs_btree_ptr *start_bno, | 196 | union xfs_btree_ptr *start_bno, |
@@ -543,6 +547,7 @@ int xfs_btree_lshift(struct xfs_btree_cur *, int, int *); | |||
543 | int xfs_btree_rshift(struct xfs_btree_cur *, int, int *); | 547 | int xfs_btree_rshift(struct xfs_btree_cur *, int, int *); |
544 | int xfs_btree_split(struct xfs_btree_cur *, int, union xfs_btree_ptr *, | 548 | int xfs_btree_split(struct xfs_btree_cur *, int, union xfs_btree_ptr *, |
545 | union xfs_btree_key *, struct xfs_btree_cur **, int *); | 549 | union xfs_btree_key *, struct xfs_btree_cur **, int *); |
550 | int xfs_btree_new_root(struct xfs_btree_cur *, int *); | ||
546 | 551 | ||
547 | /* | 552 | /* |
548 | * Helpers. | 553 | * Helpers. |
diff --git a/fs/xfs/xfs_ialloc_btree.c b/fs/xfs/xfs_ialloc_btree.c index c76190a83e4e..7ba3c7bb3984 100644 --- a/fs/xfs/xfs_ialloc_btree.c +++ b/fs/xfs/xfs_ialloc_btree.c | |||
@@ -44,7 +44,6 @@ STATIC void xfs_inobt_log_block(xfs_trans_t *, xfs_buf_t *, int); | |||
44 | STATIC void xfs_inobt_log_keys(xfs_btree_cur_t *, xfs_buf_t *, int, int); | 44 | STATIC void xfs_inobt_log_keys(xfs_btree_cur_t *, xfs_buf_t *, int, int); |
45 | STATIC void xfs_inobt_log_ptrs(xfs_btree_cur_t *, xfs_buf_t *, int, int); | 45 | STATIC void xfs_inobt_log_ptrs(xfs_btree_cur_t *, xfs_buf_t *, int, int); |
46 | STATIC void xfs_inobt_log_recs(xfs_btree_cur_t *, xfs_buf_t *, int, int); | 46 | STATIC void xfs_inobt_log_recs(xfs_btree_cur_t *, xfs_buf_t *, int, int); |
47 | STATIC int xfs_inobt_newroot(xfs_btree_cur_t *, int *); | ||
48 | 47 | ||
49 | /* | 48 | /* |
50 | * Single level of the xfs_inobt_delete record deletion routine. | 49 | * Single level of the xfs_inobt_delete record deletion routine. |
@@ -556,7 +555,7 @@ xfs_inobt_insrec( | |||
556 | * and we're done. | 555 | * and we're done. |
557 | */ | 556 | */ |
558 | if (level >= cur->bc_nlevels) { | 557 | if (level >= cur->bc_nlevels) { |
559 | error = xfs_inobt_newroot(cur, &i); | 558 | error = xfs_btree_new_root(cur, &i); |
560 | *bnop = NULLAGBLOCK; | 559 | *bnop = NULLAGBLOCK; |
561 | *stat = i; | 560 | *stat = i; |
562 | return error; | 561 | return error; |
@@ -827,152 +826,6 @@ xfs_inobt_log_recs( | |||
827 | xfs_trans_log_buf(cur->bc_tp, bp, first, last); | 826 | xfs_trans_log_buf(cur->bc_tp, bp, first, last); |
828 | } | 827 | } |
829 | 828 | ||
830 | /* | ||
831 | * Allocate a new root block, fill it in. | ||
832 | */ | ||
833 | STATIC int /* error */ | ||
834 | xfs_inobt_newroot( | ||
835 | xfs_btree_cur_t *cur, /* btree cursor */ | ||
836 | int *stat) /* success/failure */ | ||
837 | { | ||
838 | xfs_agi_t *agi; /* a.g. inode header */ | ||
839 | xfs_alloc_arg_t args; /* allocation argument structure */ | ||
840 | xfs_inobt_block_t *block; /* one half of the old root block */ | ||
841 | xfs_buf_t *bp; /* buffer containing block */ | ||
842 | int error; /* error return value */ | ||
843 | xfs_inobt_key_t *kp; /* btree key pointer */ | ||
844 | xfs_agblock_t lbno; /* left block number */ | ||
845 | xfs_buf_t *lbp; /* left buffer pointer */ | ||
846 | xfs_inobt_block_t *left; /* left btree block */ | ||
847 | xfs_buf_t *nbp; /* new (root) buffer */ | ||
848 | xfs_inobt_block_t *new; /* new (root) btree block */ | ||
849 | int nptr; /* new value for key index, 1 or 2 */ | ||
850 | xfs_inobt_ptr_t *pp; /* btree address pointer */ | ||
851 | xfs_agblock_t rbno; /* right block number */ | ||
852 | xfs_buf_t *rbp; /* right buffer pointer */ | ||
853 | xfs_inobt_block_t *right; /* right btree block */ | ||
854 | xfs_inobt_rec_t *rp; /* btree record pointer */ | ||
855 | |||
856 | ASSERT(cur->bc_nlevels < XFS_IN_MAXLEVELS(cur->bc_mp)); | ||
857 | |||
858 | /* | ||
859 | * Get a block & a buffer. | ||
860 | */ | ||
861 | agi = XFS_BUF_TO_AGI(cur->bc_private.a.agbp); | ||
862 | args.tp = cur->bc_tp; | ||
863 | args.mp = cur->bc_mp; | ||
864 | args.fsbno = XFS_AGB_TO_FSB(args.mp, cur->bc_private.a.agno, | ||
865 | be32_to_cpu(agi->agi_root)); | ||
866 | args.mod = args.minleft = args.alignment = args.total = args.wasdel = | ||
867 | args.isfl = args.userdata = args.minalignslop = 0; | ||
868 | args.minlen = args.maxlen = args.prod = 1; | ||
869 | args.type = XFS_ALLOCTYPE_NEAR_BNO; | ||
870 | if ((error = xfs_alloc_vextent(&args))) | ||
871 | return error; | ||
872 | /* | ||
873 | * None available, we fail. | ||
874 | */ | ||
875 | if (args.fsbno == NULLFSBLOCK) { | ||
876 | *stat = 0; | ||
877 | return 0; | ||
878 | } | ||
879 | ASSERT(args.len == 1); | ||
880 | nbp = xfs_btree_get_bufs(args.mp, args.tp, args.agno, args.agbno, 0); | ||
881 | new = XFS_BUF_TO_INOBT_BLOCK(nbp); | ||
882 | /* | ||
883 | * Set the root data in the a.g. inode structure. | ||
884 | */ | ||
885 | agi->agi_root = cpu_to_be32(args.agbno); | ||
886 | be32_add_cpu(&agi->agi_level, 1); | ||
887 | xfs_ialloc_log_agi(args.tp, cur->bc_private.a.agbp, | ||
888 | XFS_AGI_ROOT | XFS_AGI_LEVEL); | ||
889 | /* | ||
890 | * At the previous root level there are now two blocks: the old | ||
891 | * root, and the new block generated when it was split. | ||
892 | * We don't know which one the cursor is pointing at, so we | ||
893 | * set up variables "left" and "right" for each case. | ||
894 | */ | ||
895 | bp = cur->bc_bufs[cur->bc_nlevels - 1]; | ||
896 | block = XFS_BUF_TO_INOBT_BLOCK(bp); | ||
897 | #ifdef DEBUG | ||
898 | if ((error = xfs_btree_check_sblock(cur, block, cur->bc_nlevels - 1, bp))) | ||
899 | return error; | ||
900 | #endif | ||
901 | if (be32_to_cpu(block->bb_rightsib) != NULLAGBLOCK) { | ||
902 | /* | ||
903 | * Our block is left, pick up the right block. | ||
904 | */ | ||
905 | lbp = bp; | ||
906 | lbno = XFS_DADDR_TO_AGBNO(args.mp, XFS_BUF_ADDR(lbp)); | ||
907 | left = block; | ||
908 | rbno = be32_to_cpu(left->bb_rightsib); | ||
909 | if ((error = xfs_btree_read_bufs(args.mp, args.tp, args.agno, | ||
910 | rbno, 0, &rbp, XFS_INO_BTREE_REF))) | ||
911 | return error; | ||
912 | bp = rbp; | ||
913 | right = XFS_BUF_TO_INOBT_BLOCK(rbp); | ||
914 | if ((error = xfs_btree_check_sblock(cur, right, | ||
915 | cur->bc_nlevels - 1, rbp))) | ||
916 | return error; | ||
917 | nptr = 1; | ||
918 | } else { | ||
919 | /* | ||
920 | * Our block is right, pick up the left block. | ||
921 | */ | ||
922 | rbp = bp; | ||
923 | rbno = XFS_DADDR_TO_AGBNO(args.mp, XFS_BUF_ADDR(rbp)); | ||
924 | right = block; | ||
925 | lbno = be32_to_cpu(right->bb_leftsib); | ||
926 | if ((error = xfs_btree_read_bufs(args.mp, args.tp, args.agno, | ||
927 | lbno, 0, &lbp, XFS_INO_BTREE_REF))) | ||
928 | return error; | ||
929 | bp = lbp; | ||
930 | left = XFS_BUF_TO_INOBT_BLOCK(lbp); | ||
931 | if ((error = xfs_btree_check_sblock(cur, left, | ||
932 | cur->bc_nlevels - 1, lbp))) | ||
933 | return error; | ||
934 | nptr = 2; | ||
935 | } | ||
936 | /* | ||
937 | * Fill in the new block's btree header and log it. | ||
938 | */ | ||
939 | new->bb_magic = cpu_to_be32(xfs_magics[cur->bc_btnum]); | ||
940 | new->bb_level = cpu_to_be16(cur->bc_nlevels); | ||
941 | new->bb_numrecs = cpu_to_be16(2); | ||
942 | new->bb_leftsib = cpu_to_be32(NULLAGBLOCK); | ||
943 | new->bb_rightsib = cpu_to_be32(NULLAGBLOCK); | ||
944 | xfs_inobt_log_block(args.tp, nbp, XFS_BB_ALL_BITS); | ||
945 | ASSERT(lbno != NULLAGBLOCK && rbno != NULLAGBLOCK); | ||
946 | /* | ||
947 | * Fill in the key data in the new root. | ||
948 | */ | ||
949 | kp = XFS_INOBT_KEY_ADDR(new, 1, cur); | ||
950 | if (be16_to_cpu(left->bb_level) > 0) { | ||
951 | kp[0] = *XFS_INOBT_KEY_ADDR(left, 1, cur); | ||
952 | kp[1] = *XFS_INOBT_KEY_ADDR(right, 1, cur); | ||
953 | } else { | ||
954 | rp = XFS_INOBT_REC_ADDR(left, 1, cur); | ||
955 | kp[0].ir_startino = rp->ir_startino; | ||
956 | rp = XFS_INOBT_REC_ADDR(right, 1, cur); | ||
957 | kp[1].ir_startino = rp->ir_startino; | ||
958 | } | ||
959 | xfs_inobt_log_keys(cur, nbp, 1, 2); | ||
960 | /* | ||
961 | * Fill in the pointer data in the new root. | ||
962 | */ | ||
963 | pp = XFS_INOBT_PTR_ADDR(new, 1, cur); | ||
964 | pp[0] = cpu_to_be32(lbno); | ||
965 | pp[1] = cpu_to_be32(rbno); | ||
966 | xfs_inobt_log_ptrs(cur, nbp, 1, 2); | ||
967 | /* | ||
968 | * Fix up the cursor. | ||
969 | */ | ||
970 | xfs_btree_setbuf(cur, cur->bc_nlevels, nbp); | ||
971 | cur->bc_ptrs[cur->bc_nlevels] = nptr; | ||
972 | cur->bc_nlevels++; | ||
973 | *stat = 1; | ||
974 | return 0; | ||
975 | } | ||
976 | 829 | ||
977 | /* | 830 | /* |
978 | * Externally visible routines. | 831 | * Externally visible routines. |
@@ -1128,6 +981,20 @@ xfs_inobt_dup_cursor( | |||
1128 | cur->bc_private.a.agbp, cur->bc_private.a.agno); | 981 | cur->bc_private.a.agbp, cur->bc_private.a.agno); |
1129 | } | 982 | } |
1130 | 983 | ||
984 | STATIC void | ||
985 | xfs_inobt_set_root( | ||
986 | struct xfs_btree_cur *cur, | ||
987 | union xfs_btree_ptr *nptr, | ||
988 | int inc) /* level change */ | ||
989 | { | ||
990 | struct xfs_buf *agbp = cur->bc_private.a.agbp; | ||
991 | struct xfs_agi *agi = XFS_BUF_TO_AGI(agbp); | ||
992 | |||
993 | agi->agi_root = nptr->s; | ||
994 | be32_add_cpu(&agi->agi_level, inc); | ||
995 | xfs_ialloc_log_agi(cur->bc_tp, agbp, XFS_AGI_ROOT | XFS_AGI_LEVEL); | ||
996 | } | ||
997 | |||
1131 | STATIC int | 998 | STATIC int |
1132 | xfs_inobt_alloc_block( | 999 | xfs_inobt_alloc_block( |
1133 | struct xfs_btree_cur *cur, | 1000 | struct xfs_btree_cur *cur, |
@@ -1281,6 +1148,7 @@ static const struct xfs_btree_ops xfs_inobt_ops = { | |||
1281 | .key_len = sizeof(xfs_inobt_key_t), | 1148 | .key_len = sizeof(xfs_inobt_key_t), |
1282 | 1149 | ||
1283 | .dup_cursor = xfs_inobt_dup_cursor, | 1150 | .dup_cursor = xfs_inobt_dup_cursor, |
1151 | .set_root = xfs_inobt_set_root, | ||
1284 | .alloc_block = xfs_inobt_alloc_block, | 1152 | .alloc_block = xfs_inobt_alloc_block, |
1285 | .get_maxrecs = xfs_inobt_get_maxrecs, | 1153 | .get_maxrecs = xfs_inobt_get_maxrecs, |
1286 | .init_key_from_rec = xfs_inobt_init_key_from_rec, | 1154 | .init_key_from_rec = xfs_inobt_init_key_from_rec, |