diff options
author | Christoph Hellwig <hch@infradead.org> | 2008-10-30 01:56:43 -0400 |
---|---|---|
committer | Lachlan McIlroy <lachlan@sgi.com> | 2008-10-30 01:56:43 -0400 |
commit | 9eaead51bed957af0070a277d945744a76df0c8b (patch) | |
tree | 7b0679186c06f366c7aed30873e3395bd414953e /fs/xfs/xfs_bmap_btree.c | |
parent | 278d0ca14e889c3932a05d1a68675252a12b3466 (diff) |
[XFS] implement generic xfs_btree_rshift
Make the btree right shift code generic. Based on a patch from David
Chinner with lots of changes to follow the original btree implementations
more closely. While this loses some of the generic helper routines for
inserting/moving/removing records it also solves some of the one off bugs
in the original code and makes it easier to verify.
SGI-PV: 985583
SGI-Modid: xfs-linux-melb:xfs-kern:32196a
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_bmap_btree.c')
-rw-r--r-- | fs/xfs/xfs_bmap_btree.c | 142 |
1 files changed, 2 insertions, 140 deletions
diff --git a/fs/xfs/xfs_bmap_btree.c b/fs/xfs/xfs_bmap_btree.c index 99200a9898f7..9d18fa8aa1da 100644 --- a/fs/xfs/xfs_bmap_btree.c +++ b/fs/xfs/xfs_bmap_btree.c | |||
@@ -53,7 +53,6 @@ STATIC int xfs_bmbt_killroot(xfs_btree_cur_t *); | |||
53 | STATIC void xfs_bmbt_log_keys(xfs_btree_cur_t *, xfs_buf_t *, int, int); | 53 | STATIC void xfs_bmbt_log_keys(xfs_btree_cur_t *, xfs_buf_t *, int, int); |
54 | STATIC void xfs_bmbt_log_ptrs(xfs_btree_cur_t *, xfs_buf_t *, int, int); | 54 | STATIC void xfs_bmbt_log_ptrs(xfs_btree_cur_t *, xfs_buf_t *, int, int); |
55 | STATIC int xfs_bmbt_lshift(xfs_btree_cur_t *, int, int *); | 55 | STATIC int xfs_bmbt_lshift(xfs_btree_cur_t *, int, int *); |
56 | STATIC int xfs_bmbt_rshift(xfs_btree_cur_t *, int, int *); | ||
57 | STATIC int xfs_bmbt_split(xfs_btree_cur_t *, int, xfs_fsblock_t *, | 56 | STATIC int xfs_bmbt_split(xfs_btree_cur_t *, int, xfs_fsblock_t *, |
58 | __uint64_t *, xfs_btree_cur_t **, int *); | 57 | __uint64_t *, xfs_btree_cur_t **, int *); |
59 | 58 | ||
@@ -327,7 +326,7 @@ xfs_bmbt_delrec( | |||
327 | bno = be64_to_cpu(left->bb_rightsib); | 326 | bno = be64_to_cpu(left->bb_rightsib); |
328 | if (be16_to_cpu(left->bb_numrecs) - 1 >= | 327 | if (be16_to_cpu(left->bb_numrecs) - 1 >= |
329 | XFS_BMAP_BLOCK_IMINRECS(level, cur)) { | 328 | XFS_BMAP_BLOCK_IMINRECS(level, cur)) { |
330 | if ((error = xfs_bmbt_rshift(tcur, level, &i))) { | 329 | if ((error = xfs_btree_rshift(tcur, level, &i))) { |
331 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 330 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); |
332 | goto error0; | 331 | goto error0; |
333 | } | 332 | } |
@@ -538,7 +537,7 @@ xfs_bmbt_insrec( | |||
538 | logflags); | 537 | logflags); |
539 | block = xfs_bmbt_get_block(cur, level, &bp); | 538 | block = xfs_bmbt_get_block(cur, level, &bp); |
540 | } else { | 539 | } else { |
541 | if ((error = xfs_bmbt_rshift(cur, level, &i))) { | 540 | if ((error = xfs_btree_rshift(cur, level, &i))) { |
542 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 541 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); |
543 | return error; | 542 | return error; |
544 | } | 543 | } |
@@ -945,143 +944,6 @@ xfs_bmbt_lshift( | |||
945 | } | 944 | } |
946 | 945 | ||
947 | /* | 946 | /* |
948 | * Move 1 record right from cur/level if possible. | ||
949 | * Update cur to reflect the new path. | ||
950 | */ | ||
951 | STATIC int /* error */ | ||
952 | xfs_bmbt_rshift( | ||
953 | xfs_btree_cur_t *cur, | ||
954 | int level, | ||
955 | int *stat) /* success/failure */ | ||
956 | { | ||
957 | int error; /* error return value */ | ||
958 | int i; /* loop counter */ | ||
959 | xfs_bmbt_key_t key; /* bmap btree key */ | ||
960 | xfs_buf_t *lbp; /* left buffer pointer */ | ||
961 | xfs_bmbt_block_t *left; /* left btree block */ | ||
962 | xfs_bmbt_key_t *lkp; /* left btree key */ | ||
963 | xfs_bmbt_ptr_t *lpp; /* left address pointer */ | ||
964 | xfs_bmbt_rec_t *lrp; /* left record pointer */ | ||
965 | xfs_mount_t *mp; /* file system mount point */ | ||
966 | xfs_buf_t *rbp; /* right buffer pointer */ | ||
967 | xfs_bmbt_block_t *right; /* right btree block */ | ||
968 | xfs_bmbt_key_t *rkp; /* right btree key */ | ||
969 | xfs_bmbt_ptr_t *rpp; /* right address pointer */ | ||
970 | xfs_bmbt_rec_t *rrp=NULL; /* right record pointer */ | ||
971 | struct xfs_btree_cur *tcur; /* temporary btree cursor */ | ||
972 | |||
973 | XFS_BMBT_TRACE_CURSOR(cur, ENTRY); | ||
974 | XFS_BMBT_TRACE_ARGI(cur, level); | ||
975 | if (level == cur->bc_nlevels - 1) { | ||
976 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
977 | *stat = 0; | ||
978 | return 0; | ||
979 | } | ||
980 | lbp = cur->bc_bufs[level]; | ||
981 | left = XFS_BUF_TO_BMBT_BLOCK(lbp); | ||
982 | #ifdef DEBUG | ||
983 | if ((error = xfs_btree_check_lblock(cur, left, level, lbp))) { | ||
984 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
985 | return error; | ||
986 | } | ||
987 | #endif | ||
988 | if (be64_to_cpu(left->bb_rightsib) == NULLDFSBNO) { | ||
989 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
990 | *stat = 0; | ||
991 | return 0; | ||
992 | } | ||
993 | if (cur->bc_ptrs[level] >= be16_to_cpu(left->bb_numrecs)) { | ||
994 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
995 | *stat = 0; | ||
996 | return 0; | ||
997 | } | ||
998 | mp = cur->bc_mp; | ||
999 | if ((error = xfs_btree_read_bufl(mp, cur->bc_tp, be64_to_cpu(left->bb_rightsib), 0, | ||
1000 | &rbp, XFS_BMAP_BTREE_REF))) { | ||
1001 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
1002 | return error; | ||
1003 | } | ||
1004 | right = XFS_BUF_TO_BMBT_BLOCK(rbp); | ||
1005 | if ((error = xfs_btree_check_lblock(cur, right, level, rbp))) { | ||
1006 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
1007 | return error; | ||
1008 | } | ||
1009 | if (be16_to_cpu(right->bb_numrecs) == XFS_BMAP_BLOCK_IMAXRECS(level, cur)) { | ||
1010 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
1011 | *stat = 0; | ||
1012 | return 0; | ||
1013 | } | ||
1014 | if (level > 0) { | ||
1015 | lkp = XFS_BMAP_KEY_IADDR(left, be16_to_cpu(left->bb_numrecs), cur); | ||
1016 | lpp = XFS_BMAP_PTR_IADDR(left, be16_to_cpu(left->bb_numrecs), cur); | ||
1017 | rkp = XFS_BMAP_KEY_IADDR(right, 1, cur); | ||
1018 | rpp = XFS_BMAP_PTR_IADDR(right, 1, cur); | ||
1019 | #ifdef DEBUG | ||
1020 | for (i = be16_to_cpu(right->bb_numrecs) - 1; i >= 0; i--) { | ||
1021 | if ((error = xfs_btree_check_lptr_disk(cur, rpp[i], level))) { | ||
1022 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
1023 | return error; | ||
1024 | } | ||
1025 | } | ||
1026 | #endif | ||
1027 | memmove(rkp + 1, rkp, be16_to_cpu(right->bb_numrecs) * sizeof(*rkp)); | ||
1028 | memmove(rpp + 1, rpp, be16_to_cpu(right->bb_numrecs) * sizeof(*rpp)); | ||
1029 | #ifdef DEBUG | ||
1030 | if ((error = xfs_btree_check_lptr_disk(cur, *lpp, level))) { | ||
1031 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
1032 | return error; | ||
1033 | } | ||
1034 | #endif | ||
1035 | *rkp = *lkp; | ||
1036 | *rpp = *lpp; | ||
1037 | xfs_bmbt_log_keys(cur, rbp, 1, be16_to_cpu(right->bb_numrecs) + 1); | ||
1038 | xfs_bmbt_log_ptrs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs) + 1); | ||
1039 | } else { | ||
1040 | lrp = XFS_BMAP_REC_IADDR(left, be16_to_cpu(left->bb_numrecs), cur); | ||
1041 | rrp = XFS_BMAP_REC_IADDR(right, 1, cur); | ||
1042 | memmove(rrp + 1, rrp, be16_to_cpu(right->bb_numrecs) * sizeof(*rrp)); | ||
1043 | *rrp = *lrp; | ||
1044 | xfs_bmbt_log_recs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs) + 1); | ||
1045 | key.br_startoff = cpu_to_be64(xfs_bmbt_disk_get_startoff(rrp)); | ||
1046 | rkp = &key; | ||
1047 | } | ||
1048 | be16_add_cpu(&left->bb_numrecs, -1); | ||
1049 | xfs_bmbt_log_block(cur, lbp, XFS_BB_NUMRECS); | ||
1050 | be16_add_cpu(&right->bb_numrecs, 1); | ||
1051 | #ifdef DEBUG | ||
1052 | if (level > 0) | ||
1053 | xfs_btree_check_key(XFS_BTNUM_BMAP, rkp, rkp + 1); | ||
1054 | else | ||
1055 | xfs_btree_check_rec(XFS_BTNUM_BMAP, rrp, rrp + 1); | ||
1056 | #endif | ||
1057 | xfs_bmbt_log_block(cur, rbp, XFS_BB_NUMRECS); | ||
1058 | if ((error = xfs_btree_dup_cursor(cur, &tcur))) { | ||
1059 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
1060 | return error; | ||
1061 | } | ||
1062 | i = xfs_btree_lastrec(tcur, level); | ||
1063 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | ||
1064 | if ((error = xfs_btree_increment(tcur, level, &i))) { | ||
1065 | XFS_BMBT_TRACE_CURSOR(tcur, ERROR); | ||
1066 | goto error1; | ||
1067 | } | ||
1068 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | ||
1069 | if ((error = xfs_btree_updkey(tcur, (union xfs_btree_key *)rkp, level + 1))) { | ||
1070 | XFS_BMBT_TRACE_CURSOR(tcur, ERROR); | ||
1071 | goto error1; | ||
1072 | } | ||
1073 | xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR); | ||
1074 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); | ||
1075 | *stat = 1; | ||
1076 | return 0; | ||
1077 | error0: | ||
1078 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | ||
1079 | error1: | ||
1080 | xfs_btree_del_cursor(tcur, XFS_BTREE_ERROR); | ||
1081 | return error; | ||
1082 | } | ||
1083 | |||
1084 | /* | ||
1085 | * Determine the extent state. | 947 | * Determine the extent state. |
1086 | */ | 948 | */ |
1087 | /* ARGSUSED */ | 949 | /* ARGSUSED */ |