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_ialloc_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_ialloc_btree.c')
-rw-r--r-- | fs/xfs/xfs_ialloc_btree.c | 164 |
1 files changed, 16 insertions, 148 deletions
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, |