aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2008-10-30 01:57:16 -0400
committerLachlan McIlroy <lachlan@sgi.com>2008-10-30 01:57:16 -0400
commit344207ce8474b79be331eb93e6df4cb5bdd48ab2 (patch)
tree7858f63c359e2695a6c368a73b078ff183345922
parentf5eb8e7ca58bc1e92436614444006120d21668ba (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.c179
-rw-r--r--fs/xfs/xfs_btree.c129
-rw-r--r--fs/xfs/xfs_btree.h5
-rw-r--r--fs/xfs/xfs_ialloc_btree.c164
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);
48STATIC void xfs_alloc_log_keys(xfs_btree_cur_t *, xfs_buf_t *, int, int); 48STATIC void xfs_alloc_log_keys(xfs_btree_cur_t *, xfs_buf_t *, int, int);
49STATIC void xfs_alloc_log_ptrs(xfs_btree_cur_t *, xfs_buf_t *, int, int); 49STATIC void xfs_alloc_log_ptrs(xfs_btree_cur_t *, xfs_buf_t *, int, int);
50STATIC void xfs_alloc_log_recs(xfs_btree_cur_t *, xfs_buf_t *, int, int); 50STATIC void xfs_alloc_log_recs(xfs_btree_cur_t *, xfs_buf_t *, int, int);
51STATIC 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 */
942STATIC int /* error */
943xfs_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
1091STATIC void
1092xfs_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
1247STATIC int 1111STATIC int
1248xfs_allocbt_alloc_block( 1112xfs_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 */
2474int /* error */
2475xfs_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;
2591error0:
2592 XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR);
2593 return error;
2594out0:
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 *);
543int xfs_btree_rshift(struct xfs_btree_cur *, int, int *); 547int xfs_btree_rshift(struct xfs_btree_cur *, int, int *);
544int xfs_btree_split(struct xfs_btree_cur *, int, union xfs_btree_ptr *, 548int 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 *);
550int 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);
44STATIC void xfs_inobt_log_keys(xfs_btree_cur_t *, xfs_buf_t *, int, int); 44STATIC void xfs_inobt_log_keys(xfs_btree_cur_t *, xfs_buf_t *, int, int);
45STATIC void xfs_inobt_log_ptrs(xfs_btree_cur_t *, xfs_buf_t *, int, int); 45STATIC void xfs_inobt_log_ptrs(xfs_btree_cur_t *, xfs_buf_t *, int, int);
46STATIC void xfs_inobt_log_recs(xfs_btree_cur_t *, xfs_buf_t *, int, int); 46STATIC void xfs_inobt_log_recs(xfs_btree_cur_t *, xfs_buf_t *, int, int);
47STATIC 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 */
833STATIC int /* error */
834xfs_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
984STATIC void
985xfs_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
1131STATIC int 998STATIC int
1132xfs_inobt_alloc_block( 999xfs_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,