aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_alloc_btree.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_alloc_btree.c')
-rw-r--r--fs/xfs/xfs_alloc_btree.c179
1 files changed, 22 insertions, 157 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,