Commit 687b890a184fef263ebb773926e1f4aa69240d01
Committed by
Lachlan McIlroy
1 parent
9eaead51be
[XFS] implement generic xfs_btree_lshift
Make the btree left 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:32197a 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>
Showing 5 changed files with 192 additions and 425 deletions Side-by-side Diff
fs/xfs/xfs_alloc_btree.c
... | ... | @@ -47,7 +47,6 @@ |
47 | 47 | STATIC void xfs_alloc_log_keys(xfs_btree_cur_t *, xfs_buf_t *, int, int); |
48 | 48 | STATIC void xfs_alloc_log_ptrs(xfs_btree_cur_t *, xfs_buf_t *, int, int); |
49 | 49 | STATIC void xfs_alloc_log_recs(xfs_btree_cur_t *, xfs_buf_t *, int, int); |
50 | -STATIC int xfs_alloc_lshift(xfs_btree_cur_t *, int, int *); | |
51 | 50 | STATIC int xfs_alloc_newroot(xfs_btree_cur_t *, int *); |
52 | 51 | STATIC int xfs_alloc_split(xfs_btree_cur_t *, int, xfs_agblock_t *, |
53 | 52 | xfs_alloc_key_t *, xfs_btree_cur_t **, int *); |
... | ... | @@ -326,7 +325,7 @@ |
326 | 325 | */ |
327 | 326 | if (be16_to_cpu(right->bb_numrecs) - 1 >= |
328 | 327 | XFS_ALLOC_BLOCK_MINRECS(level, cur)) { |
329 | - if ((error = xfs_alloc_lshift(tcur, level, &i))) | |
328 | + if ((error = xfs_btree_lshift(tcur, level, &i))) | |
330 | 329 | goto error0; |
331 | 330 | if (i) { |
332 | 331 | ASSERT(be16_to_cpu(block->bb_numrecs) >= |
... | ... | @@ -691,7 +690,7 @@ |
691 | 690 | * Next, try shifting an entry to the left neighbor. |
692 | 691 | */ |
693 | 692 | else { |
694 | - if ((error = xfs_alloc_lshift(cur, level, &i))) | |
693 | + if ((error = xfs_btree_lshift(cur, level, &i))) | |
695 | 694 | return error; |
696 | 695 | if (i) |
697 | 696 | optr = ptr = cur->bc_ptrs[level]; |
... | ... | @@ -933,147 +932,6 @@ |
933 | 932 | first = (int)((xfs_caddr_t)&rp[rfirst - 1] - (xfs_caddr_t)block); |
934 | 933 | last = (int)(((xfs_caddr_t)&rp[rlast] - 1) - (xfs_caddr_t)block); |
935 | 934 | xfs_trans_log_buf(cur->bc_tp, bp, first, last); |
936 | -} | |
937 | - | |
938 | -/* | |
939 | - * Move 1 record left from cur/level if possible. | |
940 | - * Update cur to reflect the new path. | |
941 | - */ | |
942 | -STATIC int /* error */ | |
943 | -xfs_alloc_lshift( | |
944 | - xfs_btree_cur_t *cur, /* btree cursor */ | |
945 | - int level, /* level to shift record on */ | |
946 | - int *stat) /* success/failure */ | |
947 | -{ | |
948 | - int error; /* error return value */ | |
949 | -#ifdef DEBUG | |
950 | - int i; /* loop index */ | |
951 | -#endif | |
952 | - xfs_alloc_key_t key; /* key value for leaf level upward */ | |
953 | - xfs_buf_t *lbp; /* buffer for left neighbor block */ | |
954 | - xfs_alloc_block_t *left; /* left neighbor btree block */ | |
955 | - int nrec; /* new number of left block entries */ | |
956 | - xfs_buf_t *rbp; /* buffer for right (current) block */ | |
957 | - xfs_alloc_block_t *right; /* right (current) btree block */ | |
958 | - xfs_alloc_key_t *rkp=NULL; /* key pointer for right block */ | |
959 | - xfs_alloc_ptr_t *rpp=NULL; /* address pointer for right block */ | |
960 | - xfs_alloc_rec_t *rrp=NULL; /* record pointer for right block */ | |
961 | - | |
962 | - /* | |
963 | - * Set up variables for this block as "right". | |
964 | - */ | |
965 | - rbp = cur->bc_bufs[level]; | |
966 | - right = XFS_BUF_TO_ALLOC_BLOCK(rbp); | |
967 | -#ifdef DEBUG | |
968 | - if ((error = xfs_btree_check_sblock(cur, right, level, rbp))) | |
969 | - return error; | |
970 | -#endif | |
971 | - /* | |
972 | - * If we've got no left sibling then we can't shift an entry left. | |
973 | - */ | |
974 | - if (be32_to_cpu(right->bb_leftsib) == NULLAGBLOCK) { | |
975 | - *stat = 0; | |
976 | - return 0; | |
977 | - } | |
978 | - /* | |
979 | - * If the cursor entry is the one that would be moved, don't | |
980 | - * do it... it's too complicated. | |
981 | - */ | |
982 | - if (cur->bc_ptrs[level] <= 1) { | |
983 | - *stat = 0; | |
984 | - return 0; | |
985 | - } | |
986 | - /* | |
987 | - * Set up the left neighbor as "left". | |
988 | - */ | |
989 | - if ((error = xfs_btree_read_bufs(cur->bc_mp, cur->bc_tp, | |
990 | - cur->bc_private.a.agno, be32_to_cpu(right->bb_leftsib), | |
991 | - 0, &lbp, XFS_ALLOC_BTREE_REF))) | |
992 | - return error; | |
993 | - left = XFS_BUF_TO_ALLOC_BLOCK(lbp); | |
994 | - if ((error = xfs_btree_check_sblock(cur, left, level, lbp))) | |
995 | - return error; | |
996 | - /* | |
997 | - * If it's full, it can't take another entry. | |
998 | - */ | |
999 | - if (be16_to_cpu(left->bb_numrecs) == XFS_ALLOC_BLOCK_MAXRECS(level, cur)) { | |
1000 | - *stat = 0; | |
1001 | - return 0; | |
1002 | - } | |
1003 | - nrec = be16_to_cpu(left->bb_numrecs) + 1; | |
1004 | - /* | |
1005 | - * If non-leaf, copy a key and a ptr to the left block. | |
1006 | - */ | |
1007 | - if (level > 0) { | |
1008 | - xfs_alloc_key_t *lkp; /* key pointer for left block */ | |
1009 | - xfs_alloc_ptr_t *lpp; /* address pointer for left block */ | |
1010 | - | |
1011 | - lkp = XFS_ALLOC_KEY_ADDR(left, nrec, cur); | |
1012 | - rkp = XFS_ALLOC_KEY_ADDR(right, 1, cur); | |
1013 | - *lkp = *rkp; | |
1014 | - xfs_alloc_log_keys(cur, lbp, nrec, nrec); | |
1015 | - lpp = XFS_ALLOC_PTR_ADDR(left, nrec, cur); | |
1016 | - rpp = XFS_ALLOC_PTR_ADDR(right, 1, cur); | |
1017 | -#ifdef DEBUG | |
1018 | - if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(*rpp), level))) | |
1019 | - return error; | |
1020 | -#endif | |
1021 | - *lpp = *rpp; | |
1022 | - xfs_alloc_log_ptrs(cur, lbp, nrec, nrec); | |
1023 | - xfs_btree_check_key(cur->bc_btnum, lkp - 1, lkp); | |
1024 | - } | |
1025 | - /* | |
1026 | - * If leaf, copy a record to the left block. | |
1027 | - */ | |
1028 | - else { | |
1029 | - xfs_alloc_rec_t *lrp; /* record pointer for left block */ | |
1030 | - | |
1031 | - lrp = XFS_ALLOC_REC_ADDR(left, nrec, cur); | |
1032 | - rrp = XFS_ALLOC_REC_ADDR(right, 1, cur); | |
1033 | - *lrp = *rrp; | |
1034 | - xfs_alloc_log_recs(cur, lbp, nrec, nrec); | |
1035 | - xfs_btree_check_rec(cur->bc_btnum, lrp - 1, lrp); | |
1036 | - } | |
1037 | - /* | |
1038 | - * Bump and log left's numrecs, decrement and log right's numrecs. | |
1039 | - */ | |
1040 | - be16_add_cpu(&left->bb_numrecs, 1); | |
1041 | - xfs_alloc_log_block(cur->bc_tp, lbp, XFS_BB_NUMRECS); | |
1042 | - be16_add_cpu(&right->bb_numrecs, -1); | |
1043 | - xfs_alloc_log_block(cur->bc_tp, rbp, XFS_BB_NUMRECS); | |
1044 | - /* | |
1045 | - * Slide the contents of right down one entry. | |
1046 | - */ | |
1047 | - if (level > 0) { | |
1048 | -#ifdef DEBUG | |
1049 | - for (i = 0; i < be16_to_cpu(right->bb_numrecs); i++) { | |
1050 | - if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(rpp[i + 1]), | |
1051 | - level))) | |
1052 | - return error; | |
1053 | - } | |
1054 | -#endif | |
1055 | - memmove(rkp, rkp + 1, be16_to_cpu(right->bb_numrecs) * sizeof(*rkp)); | |
1056 | - memmove(rpp, rpp + 1, be16_to_cpu(right->bb_numrecs) * sizeof(*rpp)); | |
1057 | - xfs_alloc_log_keys(cur, rbp, 1, be16_to_cpu(right->bb_numrecs)); | |
1058 | - xfs_alloc_log_ptrs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs)); | |
1059 | - } else { | |
1060 | - memmove(rrp, rrp + 1, be16_to_cpu(right->bb_numrecs) * sizeof(*rrp)); | |
1061 | - xfs_alloc_log_recs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs)); | |
1062 | - key.ar_startblock = rrp->ar_startblock; | |
1063 | - key.ar_blockcount = rrp->ar_blockcount; | |
1064 | - rkp = &key; | |
1065 | - } | |
1066 | - /* | |
1067 | - * Update the parent key values of right. | |
1068 | - */ | |
1069 | - if ((error = xfs_btree_updkey(cur, (union xfs_btree_key *)rkp, level + 1))) | |
1070 | - return error; | |
1071 | - /* | |
1072 | - * Slide the cursor value left one. | |
1073 | - */ | |
1074 | - cur->bc_ptrs[level]--; | |
1075 | - *stat = 1; | |
1076 | - return 0; | |
1077 | 935 | } |
1078 | 936 | |
1079 | 937 | /* |
fs/xfs/xfs_bmap_btree.c
... | ... | @@ -52,7 +52,6 @@ |
52 | 52 | STATIC int xfs_bmbt_killroot(xfs_btree_cur_t *); |
53 | 53 | STATIC void xfs_bmbt_log_keys(xfs_btree_cur_t *, xfs_buf_t *, int, int); |
54 | 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 *); | |
56 | 55 | STATIC int xfs_bmbt_split(xfs_btree_cur_t *, int, xfs_fsblock_t *, |
57 | 56 | __uint64_t *, xfs_btree_cur_t **, int *); |
58 | 57 | |
... | ... | @@ -270,7 +269,7 @@ |
270 | 269 | bno = be64_to_cpu(right->bb_leftsib); |
271 | 270 | if (be16_to_cpu(right->bb_numrecs) - 1 >= |
272 | 271 | XFS_BMAP_BLOCK_IMINRECS(level, cur)) { |
273 | - if ((error = xfs_bmbt_lshift(tcur, level, &i))) { | |
272 | + if ((error = xfs_btree_lshift(tcur, level, &i))) { | |
274 | 273 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); |
275 | 274 | goto error0; |
276 | 275 | } |
... | ... | @@ -544,7 +543,7 @@ |
544 | 543 | if (i) { |
545 | 544 | /* nothing */ |
546 | 545 | } else { |
547 | - if ((error = xfs_bmbt_lshift(cur, level, &i))) { | |
546 | + if ((error = xfs_btree_lshift(cur, level, &i))) { | |
548 | 547 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); |
549 | 548 | return error; |
550 | 549 | } |
... | ... | @@ -808,139 +807,6 @@ |
808 | 807 | XFS_ILOG_FBROOT(cur->bc_private.b.whichfork)); |
809 | 808 | } |
810 | 809 | XFS_BMBT_TRACE_CURSOR(cur, EXIT); |
811 | -} | |
812 | - | |
813 | -/* | |
814 | - * Move 1 record left from cur/level if possible. | |
815 | - * Update cur to reflect the new path. | |
816 | - */ | |
817 | -STATIC int /* error */ | |
818 | -xfs_bmbt_lshift( | |
819 | - xfs_btree_cur_t *cur, | |
820 | - int level, | |
821 | - int *stat) /* success/failure */ | |
822 | -{ | |
823 | - int error; /* error return value */ | |
824 | -#ifdef DEBUG | |
825 | - int i; /* loop counter */ | |
826 | -#endif | |
827 | - xfs_bmbt_key_t key; /* bmap btree key */ | |
828 | - xfs_buf_t *lbp; /* left buffer pointer */ | |
829 | - xfs_bmbt_block_t *left; /* left btree block */ | |
830 | - xfs_bmbt_key_t *lkp=NULL; /* left btree key */ | |
831 | - xfs_bmbt_ptr_t *lpp; /* left address pointer */ | |
832 | - int lrecs; /* left record count */ | |
833 | - xfs_bmbt_rec_t *lrp=NULL; /* left record pointer */ | |
834 | - xfs_mount_t *mp; /* file system mount point */ | |
835 | - xfs_buf_t *rbp; /* right buffer pointer */ | |
836 | - xfs_bmbt_block_t *right; /* right btree block */ | |
837 | - xfs_bmbt_key_t *rkp=NULL; /* right btree key */ | |
838 | - xfs_bmbt_ptr_t *rpp=NULL; /* right address pointer */ | |
839 | - xfs_bmbt_rec_t *rrp=NULL; /* right record pointer */ | |
840 | - int rrecs; /* right record count */ | |
841 | - | |
842 | - XFS_BMBT_TRACE_CURSOR(cur, ENTRY); | |
843 | - XFS_BMBT_TRACE_ARGI(cur, level); | |
844 | - if (level == cur->bc_nlevels - 1) { | |
845 | - XFS_BMBT_TRACE_CURSOR(cur, EXIT); | |
846 | - *stat = 0; | |
847 | - return 0; | |
848 | - } | |
849 | - rbp = cur->bc_bufs[level]; | |
850 | - right = XFS_BUF_TO_BMBT_BLOCK(rbp); | |
851 | -#ifdef DEBUG | |
852 | - if ((error = xfs_btree_check_lblock(cur, right, level, rbp))) { | |
853 | - XFS_BMBT_TRACE_CURSOR(cur, ERROR); | |
854 | - return error; | |
855 | - } | |
856 | -#endif | |
857 | - if (be64_to_cpu(right->bb_leftsib) == NULLDFSBNO) { | |
858 | - XFS_BMBT_TRACE_CURSOR(cur, EXIT); | |
859 | - *stat = 0; | |
860 | - return 0; | |
861 | - } | |
862 | - if (cur->bc_ptrs[level] <= 1) { | |
863 | - XFS_BMBT_TRACE_CURSOR(cur, EXIT); | |
864 | - *stat = 0; | |
865 | - return 0; | |
866 | - } | |
867 | - mp = cur->bc_mp; | |
868 | - if ((error = xfs_btree_read_bufl(mp, cur->bc_tp, be64_to_cpu(right->bb_leftsib), 0, | |
869 | - &lbp, XFS_BMAP_BTREE_REF))) { | |
870 | - XFS_BMBT_TRACE_CURSOR(cur, ERROR); | |
871 | - return error; | |
872 | - } | |
873 | - left = XFS_BUF_TO_BMBT_BLOCK(lbp); | |
874 | - if ((error = xfs_btree_check_lblock(cur, left, level, lbp))) { | |
875 | - XFS_BMBT_TRACE_CURSOR(cur, ERROR); | |
876 | - return error; | |
877 | - } | |
878 | - if (be16_to_cpu(left->bb_numrecs) == XFS_BMAP_BLOCK_IMAXRECS(level, cur)) { | |
879 | - XFS_BMBT_TRACE_CURSOR(cur, EXIT); | |
880 | - *stat = 0; | |
881 | - return 0; | |
882 | - } | |
883 | - lrecs = be16_to_cpu(left->bb_numrecs) + 1; | |
884 | - if (level > 0) { | |
885 | - lkp = XFS_BMAP_KEY_IADDR(left, lrecs, cur); | |
886 | - rkp = XFS_BMAP_KEY_IADDR(right, 1, cur); | |
887 | - *lkp = *rkp; | |
888 | - xfs_bmbt_log_keys(cur, lbp, lrecs, lrecs); | |
889 | - lpp = XFS_BMAP_PTR_IADDR(left, lrecs, cur); | |
890 | - rpp = XFS_BMAP_PTR_IADDR(right, 1, cur); | |
891 | -#ifdef DEBUG | |
892 | - if ((error = xfs_btree_check_lptr_disk(cur, *rpp, level))) { | |
893 | - XFS_BMBT_TRACE_CURSOR(cur, ERROR); | |
894 | - return error; | |
895 | - } | |
896 | -#endif | |
897 | - *lpp = *rpp; | |
898 | - xfs_bmbt_log_ptrs(cur, lbp, lrecs, lrecs); | |
899 | - } else { | |
900 | - lrp = XFS_BMAP_REC_IADDR(left, lrecs, cur); | |
901 | - rrp = XFS_BMAP_REC_IADDR(right, 1, cur); | |
902 | - *lrp = *rrp; | |
903 | - xfs_bmbt_log_recs(cur, lbp, lrecs, lrecs); | |
904 | - } | |
905 | - left->bb_numrecs = cpu_to_be16(lrecs); | |
906 | - xfs_bmbt_log_block(cur, lbp, XFS_BB_NUMRECS); | |
907 | -#ifdef DEBUG | |
908 | - if (level > 0) | |
909 | - xfs_btree_check_key(XFS_BTNUM_BMAP, lkp - 1, lkp); | |
910 | - else | |
911 | - xfs_btree_check_rec(XFS_BTNUM_BMAP, lrp - 1, lrp); | |
912 | -#endif | |
913 | - rrecs = be16_to_cpu(right->bb_numrecs) - 1; | |
914 | - right->bb_numrecs = cpu_to_be16(rrecs); | |
915 | - xfs_bmbt_log_block(cur, rbp, XFS_BB_NUMRECS); | |
916 | - if (level > 0) { | |
917 | -#ifdef DEBUG | |
918 | - for (i = 0; i < rrecs; i++) { | |
919 | - if ((error = xfs_btree_check_lptr_disk(cur, rpp[i + 1], | |
920 | - level))) { | |
921 | - XFS_BMBT_TRACE_CURSOR(cur, ERROR); | |
922 | - return error; | |
923 | - } | |
924 | - } | |
925 | -#endif | |
926 | - memmove(rkp, rkp + 1, rrecs * sizeof(*rkp)); | |
927 | - memmove(rpp, rpp + 1, rrecs * sizeof(*rpp)); | |
928 | - xfs_bmbt_log_keys(cur, rbp, 1, rrecs); | |
929 | - xfs_bmbt_log_ptrs(cur, rbp, 1, rrecs); | |
930 | - } else { | |
931 | - memmove(rrp, rrp + 1, rrecs * sizeof(*rrp)); | |
932 | - xfs_bmbt_log_recs(cur, rbp, 1, rrecs); | |
933 | - key.br_startoff = cpu_to_be64(xfs_bmbt_disk_get_startoff(rrp)); | |
934 | - rkp = &key; | |
935 | - } | |
936 | - if ((error = xfs_btree_updkey(cur, (union xfs_btree_key *)rkp, level + 1))) { | |
937 | - XFS_BMBT_TRACE_CURSOR(cur, ERROR); | |
938 | - return error; | |
939 | - } | |
940 | - cur->bc_ptrs[level]--; | |
941 | - XFS_BMBT_TRACE_CURSOR(cur, EXIT); | |
942 | - *stat = 1; | |
943 | - return 0; | |
944 | 810 | } |
945 | 811 | |
946 | 812 | /* |
fs/xfs/xfs_btree.c
... | ... | @@ -1841,6 +1841,191 @@ |
1841 | 1841 | } |
1842 | 1842 | |
1843 | 1843 | /* |
1844 | + * Move 1 record left from cur/level if possible. | |
1845 | + * Update cur to reflect the new path. | |
1846 | + */ | |
1847 | +int /* error */ | |
1848 | +xfs_btree_lshift( | |
1849 | + struct xfs_btree_cur *cur, | |
1850 | + int level, | |
1851 | + int *stat) /* success/failure */ | |
1852 | +{ | |
1853 | + union xfs_btree_key key; /* btree key */ | |
1854 | + struct xfs_buf *lbp; /* left buffer pointer */ | |
1855 | + struct xfs_btree_block *left; /* left btree block */ | |
1856 | + int lrecs; /* left record count */ | |
1857 | + struct xfs_buf *rbp; /* right buffer pointer */ | |
1858 | + struct xfs_btree_block *right; /* right btree block */ | |
1859 | + int rrecs; /* right record count */ | |
1860 | + union xfs_btree_ptr lptr; /* left btree pointer */ | |
1861 | + union xfs_btree_key *rkp = NULL; /* right btree key */ | |
1862 | + union xfs_btree_ptr *rpp = NULL; /* right address pointer */ | |
1863 | + union xfs_btree_rec *rrp = NULL; /* right record pointer */ | |
1864 | + int error; /* error return value */ | |
1865 | + | |
1866 | + XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); | |
1867 | + XFS_BTREE_TRACE_ARGI(cur, level); | |
1868 | + | |
1869 | + if ((cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) && | |
1870 | + level == cur->bc_nlevels - 1) | |
1871 | + goto out0; | |
1872 | + | |
1873 | + /* Set up variables for this block as "right". */ | |
1874 | + right = xfs_btree_get_block(cur, level, &rbp); | |
1875 | + | |
1876 | +#ifdef DEBUG | |
1877 | + error = xfs_btree_check_block(cur, right, level, rbp); | |
1878 | + if (error) | |
1879 | + goto error0; | |
1880 | +#endif | |
1881 | + | |
1882 | + /* If we've got no left sibling then we can't shift an entry left. */ | |
1883 | + xfs_btree_get_sibling(cur, right, &lptr, XFS_BB_LEFTSIB); | |
1884 | + if (xfs_btree_ptr_is_null(cur, &lptr)) | |
1885 | + goto out0; | |
1886 | + | |
1887 | + /* | |
1888 | + * If the cursor entry is the one that would be moved, don't | |
1889 | + * do it... it's too complicated. | |
1890 | + */ | |
1891 | + if (cur->bc_ptrs[level] <= 1) | |
1892 | + goto out0; | |
1893 | + | |
1894 | + /* Set up the left neighbor as "left". */ | |
1895 | + error = xfs_btree_read_buf_block(cur, &lptr, level, 0, &left, &lbp); | |
1896 | + if (error) | |
1897 | + goto error0; | |
1898 | + | |
1899 | + /* If it's full, it can't take another entry. */ | |
1900 | + lrecs = xfs_btree_get_numrecs(left); | |
1901 | + if (lrecs == cur->bc_ops->get_maxrecs(cur, level)) | |
1902 | + goto out0; | |
1903 | + | |
1904 | + rrecs = xfs_btree_get_numrecs(right); | |
1905 | + | |
1906 | + /* | |
1907 | + * We add one entry to the left side and remove one for the right side. | |
1908 | + * Accout for it here, the changes will be updated on disk and logged | |
1909 | + * later. | |
1910 | + */ | |
1911 | + lrecs++; | |
1912 | + rrecs--; | |
1913 | + | |
1914 | + XFS_BTREE_STATS_INC(cur, lshift); | |
1915 | + XFS_BTREE_STATS_ADD(cur, moves, 1); | |
1916 | + | |
1917 | + /* | |
1918 | + * If non-leaf, copy a key and a ptr to the left block. | |
1919 | + * Log the changes to the left block. | |
1920 | + */ | |
1921 | + if (level > 0) { | |
1922 | + /* It's a non-leaf. Move keys and pointers. */ | |
1923 | + union xfs_btree_key *lkp; /* left btree key */ | |
1924 | + union xfs_btree_ptr *lpp; /* left address pointer */ | |
1925 | + | |
1926 | + lkp = xfs_btree_key_addr(cur, lrecs, left); | |
1927 | + rkp = xfs_btree_key_addr(cur, 1, right); | |
1928 | + | |
1929 | + lpp = xfs_btree_ptr_addr(cur, lrecs, left); | |
1930 | + rpp = xfs_btree_ptr_addr(cur, 1, right); | |
1931 | +#ifdef DEBUG | |
1932 | + error = xfs_btree_check_ptr(cur, rpp, 0, level); | |
1933 | + if (error) | |
1934 | + goto error0; | |
1935 | +#endif | |
1936 | + xfs_btree_copy_keys(cur, lkp, rkp, 1); | |
1937 | + xfs_btree_copy_ptrs(cur, lpp, rpp, 1); | |
1938 | + | |
1939 | + xfs_btree_log_keys(cur, lbp, lrecs, lrecs); | |
1940 | + xfs_btree_log_ptrs(cur, lbp, lrecs, lrecs); | |
1941 | + | |
1942 | + xfs_btree_check_key(cur->bc_btnum, | |
1943 | + xfs_btree_key_addr(cur, lrecs - 1, left), | |
1944 | + lkp); | |
1945 | + } else { | |
1946 | + /* It's a leaf. Move records. */ | |
1947 | + union xfs_btree_rec *lrp; /* left record pointer */ | |
1948 | + | |
1949 | + lrp = xfs_btree_rec_addr(cur, lrecs, left); | |
1950 | + rrp = xfs_btree_rec_addr(cur, 1, right); | |
1951 | + | |
1952 | + xfs_btree_copy_recs(cur, lrp, rrp, 1); | |
1953 | + xfs_btree_log_recs(cur, lbp, lrecs, lrecs); | |
1954 | + | |
1955 | + xfs_btree_check_rec(cur->bc_btnum, | |
1956 | + xfs_btree_rec_addr(cur, lrecs - 1, left), | |
1957 | + lrp); | |
1958 | + } | |
1959 | + | |
1960 | + xfs_btree_set_numrecs(left, lrecs); | |
1961 | + xfs_btree_log_block(cur, lbp, XFS_BB_NUMRECS); | |
1962 | + | |
1963 | + xfs_btree_set_numrecs(right, rrecs); | |
1964 | + xfs_btree_log_block(cur, rbp, XFS_BB_NUMRECS); | |
1965 | + | |
1966 | + /* | |
1967 | + * Slide the contents of right down one entry. | |
1968 | + */ | |
1969 | + XFS_BTREE_STATS_ADD(cur, moves, rrecs - 1); | |
1970 | + if (level > 0) { | |
1971 | + /* It's a nonleaf. operate on keys and ptrs */ | |
1972 | +#ifdef DEBUG | |
1973 | + int i; /* loop index */ | |
1974 | + | |
1975 | + for (i = 0; i < rrecs; i++) { | |
1976 | + error = xfs_btree_check_ptr(cur, rpp, i + 1, level); | |
1977 | + if (error) | |
1978 | + goto error0; | |
1979 | + } | |
1980 | +#endif | |
1981 | + xfs_btree_shift_keys(cur, | |
1982 | + xfs_btree_key_addr(cur, 2, right), | |
1983 | + -1, rrecs); | |
1984 | + xfs_btree_shift_ptrs(cur, | |
1985 | + xfs_btree_ptr_addr(cur, 2, right), | |
1986 | + -1, rrecs); | |
1987 | + | |
1988 | + xfs_btree_log_keys(cur, rbp, 1, rrecs); | |
1989 | + xfs_btree_log_ptrs(cur, rbp, 1, rrecs); | |
1990 | + } else { | |
1991 | + /* It's a leaf. operate on records */ | |
1992 | + xfs_btree_shift_recs(cur, | |
1993 | + xfs_btree_rec_addr(cur, 2, right), | |
1994 | + -1, rrecs); | |
1995 | + xfs_btree_log_recs(cur, rbp, 1, rrecs); | |
1996 | + | |
1997 | + /* | |
1998 | + * If it's the first record in the block, we'll need a key | |
1999 | + * structure to pass up to the next level (updkey). | |
2000 | + */ | |
2001 | + cur->bc_ops->init_key_from_rec(&key, | |
2002 | + xfs_btree_rec_addr(cur, 1, right)); | |
2003 | + rkp = &key; | |
2004 | + } | |
2005 | + | |
2006 | + /* Update the parent key values of right. */ | |
2007 | + error = xfs_btree_updkey(cur, rkp, level + 1); | |
2008 | + if (error) | |
2009 | + goto error0; | |
2010 | + | |
2011 | + /* Slide the cursor value left one. */ | |
2012 | + cur->bc_ptrs[level]--; | |
2013 | + | |
2014 | + XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); | |
2015 | + *stat = 1; | |
2016 | + return 0; | |
2017 | + | |
2018 | +out0: | |
2019 | + XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); | |
2020 | + *stat = 0; | |
2021 | + return 0; | |
2022 | + | |
2023 | +error0: | |
2024 | + XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR); | |
2025 | + return error; | |
2026 | +} | |
2027 | + | |
2028 | +/* | |
1844 | 2029 | * Move 1 record right from cur/level if possible. |
1845 | 2030 | * Update cur to reflect the new path. |
1846 | 2031 | */ |
fs/xfs/xfs_btree.h
... | ... | @@ -533,6 +533,7 @@ |
533 | 533 | int xfs_btree_lookup(struct xfs_btree_cur *, xfs_lookup_t, int *); |
534 | 534 | int xfs_btree_updkey(struct xfs_btree_cur *, union xfs_btree_key *, int); |
535 | 535 | int xfs_btree_update(struct xfs_btree_cur *, union xfs_btree_rec *); |
536 | +int xfs_btree_lshift(struct xfs_btree_cur *, int, int *); | |
536 | 537 | int xfs_btree_rshift(struct xfs_btree_cur *, int, int *); |
537 | 538 | |
538 | 539 | /* |
fs/xfs/xfs_ialloc_btree.c
... | ... | @@ -43,7 +43,6 @@ |
43 | 43 | STATIC void xfs_inobt_log_keys(xfs_btree_cur_t *, xfs_buf_t *, int, int); |
44 | 44 | STATIC void xfs_inobt_log_ptrs(xfs_btree_cur_t *, xfs_buf_t *, int, int); |
45 | 45 | STATIC void xfs_inobt_log_recs(xfs_btree_cur_t *, xfs_buf_t *, int, int); |
46 | -STATIC int xfs_inobt_lshift(xfs_btree_cur_t *, int, int *); | |
47 | 46 | STATIC int xfs_inobt_newroot(xfs_btree_cur_t *, int *); |
48 | 47 | STATIC int xfs_inobt_split(xfs_btree_cur_t *, int, xfs_agblock_t *, |
49 | 48 | xfs_inobt_key_t *, xfs_btree_cur_t **, int *); |
... | ... | @@ -276,7 +275,7 @@ |
276 | 275 | */ |
277 | 276 | if (be16_to_cpu(right->bb_numrecs) - 1 >= |
278 | 277 | XFS_INOBT_BLOCK_MINRECS(level, cur)) { |
279 | - if ((error = xfs_inobt_lshift(tcur, level, &i))) | |
278 | + if ((error = xfs_btree_lshift(tcur, level, &i))) | |
280 | 279 | goto error0; |
281 | 280 | if (i) { |
282 | 281 | ASSERT(be16_to_cpu(block->bb_numrecs) >= |
... | ... | @@ -616,7 +615,7 @@ |
616 | 615 | * Next, try shifting an entry to the left neighbor. |
617 | 616 | */ |
618 | 617 | else { |
619 | - if ((error = xfs_inobt_lshift(cur, level, &i))) | |
618 | + if ((error = xfs_btree_lshift(cur, level, &i))) | |
620 | 619 | return error; |
621 | 620 | if (i) { |
622 | 621 | optr = ptr = cur->bc_ptrs[level]; |
... | ... | @@ -824,148 +823,6 @@ |
824 | 823 | first = (int)((xfs_caddr_t)&rp[rfirst - 1] - (xfs_caddr_t)block); |
825 | 824 | last = (int)(((xfs_caddr_t)&rp[rlast] - 1) - (xfs_caddr_t)block); |
826 | 825 | xfs_trans_log_buf(cur->bc_tp, bp, first, last); |
827 | -} | |
828 | - | |
829 | -/* | |
830 | - * Move 1 record left from cur/level if possible. | |
831 | - * Update cur to reflect the new path. | |
832 | - */ | |
833 | -STATIC int /* error */ | |
834 | -xfs_inobt_lshift( | |
835 | - xfs_btree_cur_t *cur, /* btree cursor */ | |
836 | - int level, /* level to shift record on */ | |
837 | - int *stat) /* success/failure */ | |
838 | -{ | |
839 | - int error; /* error return value */ | |
840 | -#ifdef DEBUG | |
841 | - int i; /* loop index */ | |
842 | -#endif | |
843 | - xfs_inobt_key_t key; /* key value for leaf level upward */ | |
844 | - xfs_buf_t *lbp; /* buffer for left neighbor block */ | |
845 | - xfs_inobt_block_t *left; /* left neighbor btree block */ | |
846 | - xfs_inobt_key_t *lkp=NULL; /* key pointer for left block */ | |
847 | - xfs_inobt_ptr_t *lpp; /* address pointer for left block */ | |
848 | - xfs_inobt_rec_t *lrp=NULL; /* record pointer for left block */ | |
849 | - int nrec; /* new number of left block entries */ | |
850 | - xfs_buf_t *rbp; /* buffer for right (current) block */ | |
851 | - xfs_inobt_block_t *right; /* right (current) btree block */ | |
852 | - xfs_inobt_key_t *rkp=NULL; /* key pointer for right block */ | |
853 | - xfs_inobt_ptr_t *rpp=NULL; /* address pointer for right block */ | |
854 | - xfs_inobt_rec_t *rrp=NULL; /* record pointer for right block */ | |
855 | - | |
856 | - /* | |
857 | - * Set up variables for this block as "right". | |
858 | - */ | |
859 | - rbp = cur->bc_bufs[level]; | |
860 | - right = XFS_BUF_TO_INOBT_BLOCK(rbp); | |
861 | -#ifdef DEBUG | |
862 | - if ((error = xfs_btree_check_sblock(cur, right, level, rbp))) | |
863 | - return error; | |
864 | -#endif | |
865 | - /* | |
866 | - * If we've got no left sibling then we can't shift an entry left. | |
867 | - */ | |
868 | - if (be32_to_cpu(right->bb_leftsib) == NULLAGBLOCK) { | |
869 | - *stat = 0; | |
870 | - return 0; | |
871 | - } | |
872 | - /* | |
873 | - * If the cursor entry is the one that would be moved, don't | |
874 | - * do it... it's too complicated. | |
875 | - */ | |
876 | - if (cur->bc_ptrs[level] <= 1) { | |
877 | - *stat = 0; | |
878 | - return 0; | |
879 | - } | |
880 | - /* | |
881 | - * Set up the left neighbor as "left". | |
882 | - */ | |
883 | - if ((error = xfs_btree_read_bufs(cur->bc_mp, cur->bc_tp, | |
884 | - cur->bc_private.a.agno, be32_to_cpu(right->bb_leftsib), | |
885 | - 0, &lbp, XFS_INO_BTREE_REF))) | |
886 | - return error; | |
887 | - left = XFS_BUF_TO_INOBT_BLOCK(lbp); | |
888 | - if ((error = xfs_btree_check_sblock(cur, left, level, lbp))) | |
889 | - return error; | |
890 | - /* | |
891 | - * If it's full, it can't take another entry. | |
892 | - */ | |
893 | - if (be16_to_cpu(left->bb_numrecs) == XFS_INOBT_BLOCK_MAXRECS(level, cur)) { | |
894 | - *stat = 0; | |
895 | - return 0; | |
896 | - } | |
897 | - nrec = be16_to_cpu(left->bb_numrecs) + 1; | |
898 | - /* | |
899 | - * If non-leaf, copy a key and a ptr to the left block. | |
900 | - */ | |
901 | - if (level > 0) { | |
902 | - lkp = XFS_INOBT_KEY_ADDR(left, nrec, cur); | |
903 | - rkp = XFS_INOBT_KEY_ADDR(right, 1, cur); | |
904 | - *lkp = *rkp; | |
905 | - xfs_inobt_log_keys(cur, lbp, nrec, nrec); | |
906 | - lpp = XFS_INOBT_PTR_ADDR(left, nrec, cur); | |
907 | - rpp = XFS_INOBT_PTR_ADDR(right, 1, cur); | |
908 | -#ifdef DEBUG | |
909 | - if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(*rpp), level))) | |
910 | - return error; | |
911 | -#endif | |
912 | - *lpp = *rpp; | |
913 | - xfs_inobt_log_ptrs(cur, lbp, nrec, nrec); | |
914 | - } | |
915 | - /* | |
916 | - * If leaf, copy a record to the left block. | |
917 | - */ | |
918 | - else { | |
919 | - lrp = XFS_INOBT_REC_ADDR(left, nrec, cur); | |
920 | - rrp = XFS_INOBT_REC_ADDR(right, 1, cur); | |
921 | - *lrp = *rrp; | |
922 | - xfs_inobt_log_recs(cur, lbp, nrec, nrec); | |
923 | - } | |
924 | - /* | |
925 | - * Bump and log left's numrecs, decrement and log right's numrecs. | |
926 | - */ | |
927 | - be16_add_cpu(&left->bb_numrecs, 1); | |
928 | - xfs_inobt_log_block(cur->bc_tp, lbp, XFS_BB_NUMRECS); | |
929 | -#ifdef DEBUG | |
930 | - if (level > 0) | |
931 | - xfs_btree_check_key(cur->bc_btnum, lkp - 1, lkp); | |
932 | - else | |
933 | - xfs_btree_check_rec(cur->bc_btnum, lrp - 1, lrp); | |
934 | -#endif | |
935 | - be16_add_cpu(&right->bb_numrecs, -1); | |
936 | - xfs_inobt_log_block(cur->bc_tp, rbp, XFS_BB_NUMRECS); | |
937 | - /* | |
938 | - * Slide the contents of right down one entry. | |
939 | - */ | |
940 | - if (level > 0) { | |
941 | -#ifdef DEBUG | |
942 | - for (i = 0; i < be16_to_cpu(right->bb_numrecs); i++) { | |
943 | - if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(rpp[i + 1]), | |
944 | - level))) | |
945 | - return error; | |
946 | - } | |
947 | -#endif | |
948 | - memmove(rkp, rkp + 1, be16_to_cpu(right->bb_numrecs) * sizeof(*rkp)); | |
949 | - memmove(rpp, rpp + 1, be16_to_cpu(right->bb_numrecs) * sizeof(*rpp)); | |
950 | - xfs_inobt_log_keys(cur, rbp, 1, be16_to_cpu(right->bb_numrecs)); | |
951 | - xfs_inobt_log_ptrs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs)); | |
952 | - } else { | |
953 | - memmove(rrp, rrp + 1, be16_to_cpu(right->bb_numrecs) * sizeof(*rrp)); | |
954 | - xfs_inobt_log_recs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs)); | |
955 | - key.ir_startino = rrp->ir_startino; | |
956 | - rkp = &key; | |
957 | - } | |
958 | - /* | |
959 | - * Update the parent key values of right. | |
960 | - */ | |
961 | - if ((error = xfs_btree_updkey(cur, (union xfs_btree_key *)rkp, level + 1))) | |
962 | - return error; | |
963 | - /* | |
964 | - * Slide the cursor value left one. | |
965 | - */ | |
966 | - cur->bc_ptrs[level]--; | |
967 | - *stat = 1; | |
968 | - return 0; | |
969 | 826 | } |
970 | 827 | |
971 | 828 | /* |