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 /fs/xfs/xfs_alloc_btree.c | |
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>
Diffstat (limited to 'fs/xfs/xfs_alloc_btree.c')
-rw-r--r-- | fs/xfs/xfs_alloc_btree.c | 179 |
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); | |||
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, |