Commit 4b22a57188d87e873346b73c227607715be96399
Committed by
Lachlan McIlroy
1 parent
ea77b0a66e
[XFS] implement generic xfs_btree_insert/insrec
Make the btree insert 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:32202a 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 11 changed files with 494 additions and 873 deletions Side-by-side Diff
fs/xfs/xfs_alloc.c
... | ... | @@ -408,7 +408,7 @@ |
408 | 408 | if ((error = xfs_alloc_lookup_eq(cnt_cur, nfbno1, nflen1, &i))) |
409 | 409 | return error; |
410 | 410 | XFS_WANT_CORRUPTED_RETURN(i == 0); |
411 | - if ((error = xfs_alloc_insert(cnt_cur, &i))) | |
411 | + if ((error = xfs_btree_insert(cnt_cur, &i))) | |
412 | 412 | return error; |
413 | 413 | XFS_WANT_CORRUPTED_RETURN(i == 1); |
414 | 414 | } |
... | ... | @@ -416,7 +416,7 @@ |
416 | 416 | if ((error = xfs_alloc_lookup_eq(cnt_cur, nfbno2, nflen2, &i))) |
417 | 417 | return error; |
418 | 418 | XFS_WANT_CORRUPTED_RETURN(i == 0); |
419 | - if ((error = xfs_alloc_insert(cnt_cur, &i))) | |
419 | + if ((error = xfs_btree_insert(cnt_cur, &i))) | |
420 | 420 | return error; |
421 | 421 | XFS_WANT_CORRUPTED_RETURN(i == 1); |
422 | 422 | } |
... | ... | @@ -444,7 +444,7 @@ |
444 | 444 | if ((error = xfs_alloc_lookup_eq(bno_cur, nfbno2, nflen2, &i))) |
445 | 445 | return error; |
446 | 446 | XFS_WANT_CORRUPTED_RETURN(i == 0); |
447 | - if ((error = xfs_alloc_insert(bno_cur, &i))) | |
447 | + if ((error = xfs_btree_insert(bno_cur, &i))) | |
448 | 448 | return error; |
449 | 449 | XFS_WANT_CORRUPTED_RETURN(i == 1); |
450 | 450 | } |
... | ... | @@ -1756,7 +1756,7 @@ |
1756 | 1756 | else { |
1757 | 1757 | nbno = bno; |
1758 | 1758 | nlen = len; |
1759 | - if ((error = xfs_alloc_insert(bno_cur, &i))) | |
1759 | + if ((error = xfs_btree_insert(bno_cur, &i))) | |
1760 | 1760 | goto error0; |
1761 | 1761 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); |
1762 | 1762 | } |
... | ... | @@ -1768,7 +1768,7 @@ |
1768 | 1768 | if ((error = xfs_alloc_lookup_eq(cnt_cur, nbno, nlen, &i))) |
1769 | 1769 | goto error0; |
1770 | 1770 | XFS_WANT_CORRUPTED_GOTO(i == 0, error0); |
1771 | - if ((error = xfs_alloc_insert(cnt_cur, &i))) | |
1771 | + if ((error = xfs_btree_insert(cnt_cur, &i))) | |
1772 | 1772 | goto error0; |
1773 | 1773 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); |
1774 | 1774 | xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR); |
fs/xfs/xfs_alloc_btree.c
... | ... | @@ -583,256 +583,6 @@ |
583 | 583 | } |
584 | 584 | |
585 | 585 | /* |
586 | - * Insert one record/level. Return information to the caller | |
587 | - * allowing the next level up to proceed if necessary. | |
588 | - */ | |
589 | -STATIC int /* error */ | |
590 | -xfs_alloc_insrec( | |
591 | - xfs_btree_cur_t *cur, /* btree cursor */ | |
592 | - int level, /* level to insert record at */ | |
593 | - xfs_agblock_t *bnop, /* i/o: block number inserted */ | |
594 | - xfs_alloc_rec_t *recp, /* i/o: record data inserted */ | |
595 | - xfs_btree_cur_t **curp, /* output: new cursor replacing cur */ | |
596 | - int *stat) /* output: success/failure */ | |
597 | -{ | |
598 | - xfs_agf_t *agf; /* allocation group freelist header */ | |
599 | - xfs_alloc_block_t *block; /* btree block record/key lives in */ | |
600 | - xfs_buf_t *bp; /* buffer for block */ | |
601 | - int error; /* error return value */ | |
602 | - int i; /* loop index */ | |
603 | - xfs_alloc_key_t key; /* key value being inserted */ | |
604 | - xfs_alloc_key_t *kp; /* pointer to btree keys */ | |
605 | - xfs_agblock_t nbno; /* block number of allocated block */ | |
606 | - xfs_btree_cur_t *ncur; /* new cursor to be used at next lvl */ | |
607 | - xfs_alloc_key_t nkey; /* new key value, from split */ | |
608 | - xfs_alloc_rec_t nrec; /* new record value, for caller */ | |
609 | - int numrecs; | |
610 | - int optr; /* old ptr value */ | |
611 | - xfs_alloc_ptr_t *pp; /* pointer to btree addresses */ | |
612 | - int ptr; /* index in btree block for this rec */ | |
613 | - xfs_alloc_rec_t *rp; /* pointer to btree records */ | |
614 | - | |
615 | - ASSERT(be32_to_cpu(recp->ar_blockcount) > 0); | |
616 | - | |
617 | - /* | |
618 | - * GCC doesn't understand the (arguably complex) control flow in | |
619 | - * this function and complains about uninitialized structure fields | |
620 | - * without this. | |
621 | - */ | |
622 | - memset(&nrec, 0, sizeof(nrec)); | |
623 | - | |
624 | - /* | |
625 | - * If we made it to the root level, allocate a new root block | |
626 | - * and we're done. | |
627 | - */ | |
628 | - if (level >= cur->bc_nlevels) { | |
629 | - XFS_STATS_INC(xs_abt_insrec); | |
630 | - if ((error = xfs_btree_new_root(cur, &i))) | |
631 | - return error; | |
632 | - *bnop = NULLAGBLOCK; | |
633 | - *stat = i; | |
634 | - return 0; | |
635 | - } | |
636 | - /* | |
637 | - * Make a key out of the record data to be inserted, and save it. | |
638 | - */ | |
639 | - key.ar_startblock = recp->ar_startblock; | |
640 | - key.ar_blockcount = recp->ar_blockcount; | |
641 | - optr = ptr = cur->bc_ptrs[level]; | |
642 | - /* | |
643 | - * If we're off the left edge, return failure. | |
644 | - */ | |
645 | - if (ptr == 0) { | |
646 | - *stat = 0; | |
647 | - return 0; | |
648 | - } | |
649 | - XFS_STATS_INC(xs_abt_insrec); | |
650 | - /* | |
651 | - * Get pointers to the btree buffer and block. | |
652 | - */ | |
653 | - bp = cur->bc_bufs[level]; | |
654 | - block = XFS_BUF_TO_ALLOC_BLOCK(bp); | |
655 | - numrecs = be16_to_cpu(block->bb_numrecs); | |
656 | -#ifdef DEBUG | |
657 | - if ((error = xfs_btree_check_sblock(cur, block, level, bp))) | |
658 | - return error; | |
659 | - /* | |
660 | - * Check that the new entry is being inserted in the right place. | |
661 | - */ | |
662 | - if (ptr <= numrecs) { | |
663 | - if (level == 0) { | |
664 | - rp = XFS_ALLOC_REC_ADDR(block, ptr, cur); | |
665 | - xfs_btree_check_rec(cur->bc_btnum, recp, rp); | |
666 | - } else { | |
667 | - kp = XFS_ALLOC_KEY_ADDR(block, ptr, cur); | |
668 | - xfs_btree_check_key(cur->bc_btnum, &key, kp); | |
669 | - } | |
670 | - } | |
671 | -#endif | |
672 | - nbno = NULLAGBLOCK; | |
673 | - ncur = NULL; | |
674 | - /* | |
675 | - * If the block is full, we can't insert the new entry until we | |
676 | - * make the block un-full. | |
677 | - */ | |
678 | - if (numrecs == XFS_ALLOC_BLOCK_MAXRECS(level, cur)) { | |
679 | - /* | |
680 | - * First, try shifting an entry to the right neighbor. | |
681 | - */ | |
682 | - if ((error = xfs_btree_rshift(cur, level, &i))) | |
683 | - return error; | |
684 | - if (i) { | |
685 | - /* nothing */ | |
686 | - } | |
687 | - /* | |
688 | - * Next, try shifting an entry to the left neighbor. | |
689 | - */ | |
690 | - else { | |
691 | - if ((error = xfs_btree_lshift(cur, level, &i))) | |
692 | - return error; | |
693 | - if (i) | |
694 | - optr = ptr = cur->bc_ptrs[level]; | |
695 | - else { | |
696 | - union xfs_btree_ptr bno = { .s = cpu_to_be32(nbno) }; | |
697 | - /* | |
698 | - * Next, try splitting the current block in | |
699 | - * half. If this works we have to re-set our | |
700 | - * variables because we could be in a | |
701 | - * different block now. | |
702 | - */ | |
703 | - if ((error = xfs_btree_split(cur, level, &bno, | |
704 | - (union xfs_btree_key *)&nkey, | |
705 | - &ncur, &i))) | |
706 | - return error; | |
707 | - nbno = be32_to_cpu(bno.s); | |
708 | - if (i) { | |
709 | - bp = cur->bc_bufs[level]; | |
710 | - block = XFS_BUF_TO_ALLOC_BLOCK(bp); | |
711 | -#ifdef DEBUG | |
712 | - if ((error = | |
713 | - xfs_btree_check_sblock(cur, | |
714 | - block, level, bp))) | |
715 | - return error; | |
716 | -#endif | |
717 | - ptr = cur->bc_ptrs[level]; | |
718 | - nrec.ar_startblock = nkey.ar_startblock; | |
719 | - nrec.ar_blockcount = nkey.ar_blockcount; | |
720 | - } | |
721 | - /* | |
722 | - * Otherwise the insert fails. | |
723 | - */ | |
724 | - else { | |
725 | - *stat = 0; | |
726 | - return 0; | |
727 | - } | |
728 | - } | |
729 | - } | |
730 | - } | |
731 | - /* | |
732 | - * At this point we know there's room for our new entry in the block | |
733 | - * we're pointing at. | |
734 | - */ | |
735 | - numrecs = be16_to_cpu(block->bb_numrecs); | |
736 | - if (level > 0) { | |
737 | - /* | |
738 | - * It's a non-leaf entry. Make a hole for the new data | |
739 | - * in the key and ptr regions of the block. | |
740 | - */ | |
741 | - kp = XFS_ALLOC_KEY_ADDR(block, 1, cur); | |
742 | - pp = XFS_ALLOC_PTR_ADDR(block, 1, cur); | |
743 | -#ifdef DEBUG | |
744 | - for (i = numrecs; i >= ptr; i--) { | |
745 | - if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(pp[i - 1]), level))) | |
746 | - return error; | |
747 | - } | |
748 | -#endif | |
749 | - memmove(&kp[ptr], &kp[ptr - 1], | |
750 | - (numrecs - ptr + 1) * sizeof(*kp)); | |
751 | - memmove(&pp[ptr], &pp[ptr - 1], | |
752 | - (numrecs - ptr + 1) * sizeof(*pp)); | |
753 | -#ifdef DEBUG | |
754 | - if ((error = xfs_btree_check_sptr(cur, *bnop, level))) | |
755 | - return error; | |
756 | -#endif | |
757 | - /* | |
758 | - * Now stuff the new data in, bump numrecs and log the new data. | |
759 | - */ | |
760 | - kp[ptr - 1] = key; | |
761 | - pp[ptr - 1] = cpu_to_be32(*bnop); | |
762 | - numrecs++; | |
763 | - block->bb_numrecs = cpu_to_be16(numrecs); | |
764 | - xfs_alloc_log_keys(cur, bp, ptr, numrecs); | |
765 | - xfs_alloc_log_ptrs(cur, bp, ptr, numrecs); | |
766 | -#ifdef DEBUG | |
767 | - if (ptr < numrecs) | |
768 | - xfs_btree_check_key(cur->bc_btnum, kp + ptr - 1, | |
769 | - kp + ptr); | |
770 | -#endif | |
771 | - } else { | |
772 | - /* | |
773 | - * It's a leaf entry. Make a hole for the new record. | |
774 | - */ | |
775 | - rp = XFS_ALLOC_REC_ADDR(block, 1, cur); | |
776 | - memmove(&rp[ptr], &rp[ptr - 1], | |
777 | - (numrecs - ptr + 1) * sizeof(*rp)); | |
778 | - /* | |
779 | - * Now stuff the new record in, bump numrecs | |
780 | - * and log the new data. | |
781 | - */ | |
782 | - rp[ptr - 1] = *recp; | |
783 | - numrecs++; | |
784 | - block->bb_numrecs = cpu_to_be16(numrecs); | |
785 | - xfs_alloc_log_recs(cur, bp, ptr, numrecs); | |
786 | -#ifdef DEBUG | |
787 | - if (ptr < numrecs) | |
788 | - xfs_btree_check_rec(cur->bc_btnum, rp + ptr - 1, | |
789 | - rp + ptr); | |
790 | -#endif | |
791 | - } | |
792 | - /* | |
793 | - * Log the new number of records in the btree header. | |
794 | - */ | |
795 | - xfs_alloc_log_block(cur->bc_tp, bp, XFS_BB_NUMRECS); | |
796 | - /* | |
797 | - * If we inserted at the start of a block, update the parents' keys. | |
798 | - */ | |
799 | - if (optr == 1 && (error = xfs_btree_updkey(cur, (union xfs_btree_key *)&key, level + 1))) | |
800 | - return error; | |
801 | - /* | |
802 | - * Look to see if the longest extent in the allocation group | |
803 | - * needs to be updated. | |
804 | - */ | |
805 | - | |
806 | - agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp); | |
807 | - if (level == 0 && | |
808 | - cur->bc_btnum == XFS_BTNUM_CNT && | |
809 | - be32_to_cpu(block->bb_rightsib) == NULLAGBLOCK && | |
810 | - be32_to_cpu(recp->ar_blockcount) > be32_to_cpu(agf->agf_longest)) { | |
811 | - /* | |
812 | - * If this is a leaf in the by-size btree and there | |
813 | - * is no right sibling block and this block is bigger | |
814 | - * than the previous longest block, update it. | |
815 | - */ | |
816 | - agf->agf_longest = recp->ar_blockcount; | |
817 | - cur->bc_mp->m_perag[be32_to_cpu(agf->agf_seqno)].pagf_longest | |
818 | - = be32_to_cpu(recp->ar_blockcount); | |
819 | - xfs_alloc_log_agf(cur->bc_tp, cur->bc_private.a.agbp, | |
820 | - XFS_AGF_LONGEST); | |
821 | - } | |
822 | - /* | |
823 | - * Return the new block number, if any. | |
824 | - * If there is one, give back a record value and a cursor too. | |
825 | - */ | |
826 | - *bnop = nbno; | |
827 | - if (nbno != NULLAGBLOCK) { | |
828 | - *recp = nrec; | |
829 | - *curp = ncur; | |
830 | - } | |
831 | - *stat = 1; | |
832 | - return 0; | |
833 | -} | |
834 | - | |
835 | -/* | |
836 | 586 | * Log header fields from a btree block. |
837 | 587 | */ |
838 | 588 | STATIC void |
839 | 589 | |
... | ... | @@ -1019,66 +769,7 @@ |
1019 | 769 | return 0; |
1020 | 770 | } |
1021 | 771 | |
1022 | -/* | |
1023 | - * Insert the current record at the point referenced by cur. | |
1024 | - * The cursor may be inconsistent on return if splits have been done. | |
1025 | - */ | |
1026 | -int /* error */ | |
1027 | -xfs_alloc_insert( | |
1028 | - xfs_btree_cur_t *cur, /* btree cursor */ | |
1029 | - int *stat) /* success/failure */ | |
1030 | -{ | |
1031 | - int error; /* error return value */ | |
1032 | - int i; /* result value, 0 for failure */ | |
1033 | - int level; /* current level number in btree */ | |
1034 | - xfs_agblock_t nbno; /* new block number (split result) */ | |
1035 | - xfs_btree_cur_t *ncur; /* new cursor (split result) */ | |
1036 | - xfs_alloc_rec_t nrec; /* record being inserted this level */ | |
1037 | - xfs_btree_cur_t *pcur; /* previous level's cursor */ | |
1038 | 772 | |
1039 | - level = 0; | |
1040 | - nbno = NULLAGBLOCK; | |
1041 | - nrec.ar_startblock = cpu_to_be32(cur->bc_rec.a.ar_startblock); | |
1042 | - nrec.ar_blockcount = cpu_to_be32(cur->bc_rec.a.ar_blockcount); | |
1043 | - ncur = NULL; | |
1044 | - pcur = cur; | |
1045 | - /* | |
1046 | - * Loop going up the tree, starting at the leaf level. | |
1047 | - * Stop when we don't get a split block, that must mean that | |
1048 | - * the insert is finished with this level. | |
1049 | - */ | |
1050 | - do { | |
1051 | - /* | |
1052 | - * Insert nrec/nbno into this level of the tree. | |
1053 | - * Note if we fail, nbno will be null. | |
1054 | - */ | |
1055 | - if ((error = xfs_alloc_insrec(pcur, level++, &nbno, &nrec, &ncur, | |
1056 | - &i))) { | |
1057 | - if (pcur != cur) | |
1058 | - xfs_btree_del_cursor(pcur, XFS_BTREE_ERROR); | |
1059 | - return error; | |
1060 | - } | |
1061 | - /* | |
1062 | - * See if the cursor we just used is trash. | |
1063 | - * Can't trash the caller's cursor, but otherwise we should | |
1064 | - * if ncur is a new cursor or we're about to be done. | |
1065 | - */ | |
1066 | - if (pcur != cur && (ncur || nbno == NULLAGBLOCK)) { | |
1067 | - cur->bc_nlevels = pcur->bc_nlevels; | |
1068 | - xfs_btree_del_cursor(pcur, XFS_BTREE_NOERROR); | |
1069 | - } | |
1070 | - /* | |
1071 | - * If we got a new cursor, switch to it. | |
1072 | - */ | |
1073 | - if (ncur) { | |
1074 | - pcur = ncur; | |
1075 | - ncur = NULL; | |
1076 | - } | |
1077 | - } while (nbno != NULLAGBLOCK); | |
1078 | - *stat = i; | |
1079 | - return 0; | |
1080 | -} | |
1081 | - | |
1082 | 773 | STATIC struct xfs_btree_cur * |
1083 | 774 | xfs_allocbt_dup_cursor( |
1084 | 775 | struct xfs_btree_cur *cur) |
... | ... | @@ -1170,6 +861,12 @@ |
1170 | 861 | return; |
1171 | 862 | len = rec->alloc.ar_blockcount; |
1172 | 863 | break; |
864 | + case LASTREC_INSREC: | |
865 | + if (be32_to_cpu(rec->alloc.ar_blockcount) <= | |
866 | + be32_to_cpu(agf->agf_longest)) | |
867 | + return; | |
868 | + len = rec->alloc.ar_blockcount; | |
869 | + break; | |
1173 | 870 | default: |
1174 | 871 | ASSERT(0); |
1175 | 872 | return; |
... | ... | @@ -1200,6 +897,28 @@ |
1200 | 897 | } |
1201 | 898 | |
1202 | 899 | STATIC void |
900 | +xfs_allocbt_init_rec_from_key( | |
901 | + union xfs_btree_key *key, | |
902 | + union xfs_btree_rec *rec) | |
903 | +{ | |
904 | + ASSERT(key->alloc.ar_startblock != 0); | |
905 | + | |
906 | + rec->alloc.ar_startblock = key->alloc.ar_startblock; | |
907 | + rec->alloc.ar_blockcount = key->alloc.ar_blockcount; | |
908 | +} | |
909 | + | |
910 | +STATIC void | |
911 | +xfs_allocbt_init_rec_from_cur( | |
912 | + struct xfs_btree_cur *cur, | |
913 | + union xfs_btree_rec *rec) | |
914 | +{ | |
915 | + ASSERT(cur->bc_rec.a.ar_startblock != 0); | |
916 | + | |
917 | + rec->alloc.ar_startblock = cpu_to_be32(cur->bc_rec.a.ar_startblock); | |
918 | + rec->alloc.ar_blockcount = cpu_to_be32(cur->bc_rec.a.ar_blockcount); | |
919 | +} | |
920 | + | |
921 | +STATIC void | |
1203 | 922 | xfs_allocbt_init_ptr_from_cur( |
1204 | 923 | struct xfs_btree_cur *cur, |
1205 | 924 | union xfs_btree_ptr *ptr) |
... | ... | @@ -1309,6 +1028,8 @@ |
1309 | 1028 | .update_lastrec = xfs_allocbt_update_lastrec, |
1310 | 1029 | .get_maxrecs = xfs_allocbt_get_maxrecs, |
1311 | 1030 | .init_key_from_rec = xfs_allocbt_init_key_from_rec, |
1031 | + .init_rec_from_key = xfs_allocbt_init_rec_from_key, | |
1032 | + .init_rec_from_cur = xfs_allocbt_init_rec_from_cur, | |
1312 | 1033 | .init_ptr_from_cur = xfs_allocbt_init_ptr_from_cur, |
1313 | 1034 | .key_diff = xfs_allocbt_key_diff, |
1314 | 1035 |
fs/xfs/xfs_alloc_btree.h
... | ... | @@ -107,12 +107,6 @@ |
107 | 107 | extern int xfs_alloc_get_rec(struct xfs_btree_cur *cur, xfs_agblock_t *bno, |
108 | 108 | xfs_extlen_t *len, int *stat); |
109 | 109 | |
110 | -/* | |
111 | - * Insert the current record at the point referenced by cur. | |
112 | - * The cursor may be inconsistent on return if splits have been done. | |
113 | - */ | |
114 | -extern int xfs_alloc_insert(struct xfs_btree_cur *cur, int *stat); | |
115 | - | |
116 | 110 | |
117 | 111 | extern struct xfs_btree_cur *xfs_allocbt_init_cursor(struct xfs_mount *, |
118 | 112 | struct xfs_trans *, struct xfs_buf *, |
fs/xfs/xfs_bmap.c
... | ... | @@ -977,7 +977,7 @@ |
977 | 977 | goto done; |
978 | 978 | XFS_WANT_CORRUPTED_GOTO(i == 0, done); |
979 | 979 | cur->bc_rec.b.br_state = XFS_EXT_NORM; |
980 | - if ((error = xfs_bmbt_insert(cur, &i))) | |
980 | + if ((error = xfs_btree_insert(cur, &i))) | |
981 | 981 | goto done; |
982 | 982 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); |
983 | 983 | } |
... | ... | @@ -1053,7 +1053,7 @@ |
1053 | 1053 | goto done; |
1054 | 1054 | XFS_WANT_CORRUPTED_GOTO(i == 0, done); |
1055 | 1055 | cur->bc_rec.b.br_state = XFS_EXT_NORM; |
1056 | - if ((error = xfs_bmbt_insert(cur, &i))) | |
1056 | + if ((error = xfs_btree_insert(cur, &i))) | |
1057 | 1057 | goto done; |
1058 | 1058 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); |
1059 | 1059 | } |
... | ... | @@ -1143,7 +1143,7 @@ |
1143 | 1143 | goto done; |
1144 | 1144 | XFS_WANT_CORRUPTED_GOTO(i == 0, done); |
1145 | 1145 | cur->bc_rec.b.br_state = XFS_EXT_NORM; |
1146 | - if ((error = xfs_bmbt_insert(cur, &i))) | |
1146 | + if ((error = xfs_btree_insert(cur, &i))) | |
1147 | 1147 | goto done; |
1148 | 1148 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); |
1149 | 1149 | } |
... | ... | @@ -1198,7 +1198,7 @@ |
1198 | 1198 | goto done; |
1199 | 1199 | XFS_WANT_CORRUPTED_GOTO(i == 0, done); |
1200 | 1200 | cur->bc_rec.b.br_state = XFS_EXT_NORM; |
1201 | - if ((error = xfs_bmbt_insert(cur, &i))) | |
1201 | + if ((error = xfs_btree_insert(cur, &i))) | |
1202 | 1202 | goto done; |
1203 | 1203 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); |
1204 | 1204 | } |
... | ... | @@ -1651,7 +1651,7 @@ |
1651 | 1651 | oldext))) |
1652 | 1652 | goto done; |
1653 | 1653 | cur->bc_rec.b = *new; |
1654 | - if ((error = xfs_bmbt_insert(cur, &i))) | |
1654 | + if ((error = xfs_btree_insert(cur, &i))) | |
1655 | 1655 | goto done; |
1656 | 1656 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); |
1657 | 1657 | } |
... | ... | @@ -1741,7 +1741,7 @@ |
1741 | 1741 | goto done; |
1742 | 1742 | XFS_WANT_CORRUPTED_GOTO(i == 0, done); |
1743 | 1743 | cur->bc_rec.b.br_state = XFS_EXT_NORM; |
1744 | - if ((error = xfs_bmbt_insert(cur, &i))) | |
1744 | + if ((error = xfs_btree_insert(cur, &i))) | |
1745 | 1745 | goto done; |
1746 | 1746 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); |
1747 | 1747 | } |
... | ... | @@ -1789,7 +1789,7 @@ |
1789 | 1789 | cur->bc_rec.b = PREV; |
1790 | 1790 | cur->bc_rec.b.br_blockcount = |
1791 | 1791 | new->br_startoff - PREV.br_startoff; |
1792 | - if ((error = xfs_bmbt_insert(cur, &i))) | |
1792 | + if ((error = xfs_btree_insert(cur, &i))) | |
1793 | 1793 | goto done; |
1794 | 1794 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); |
1795 | 1795 | /* |
... | ... | @@ -1804,7 +1804,7 @@ |
1804 | 1804 | XFS_WANT_CORRUPTED_GOTO(i == 0, done); |
1805 | 1805 | /* new middle extent - newext */ |
1806 | 1806 | cur->bc_rec.b.br_state = new->br_state; |
1807 | - if ((error = xfs_bmbt_insert(cur, &i))) | |
1807 | + if ((error = xfs_btree_insert(cur, &i))) | |
1808 | 1808 | goto done; |
1809 | 1809 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); |
1810 | 1810 | } |
... | ... | @@ -2264,7 +2264,7 @@ |
2264 | 2264 | goto done; |
2265 | 2265 | XFS_WANT_CORRUPTED_GOTO(i == 0, done); |
2266 | 2266 | cur->bc_rec.b.br_state = new->br_state; |
2267 | - if ((error = xfs_bmbt_insert(cur, &i))) | |
2267 | + if ((error = xfs_btree_insert(cur, &i))) | |
2268 | 2268 | goto done; |
2269 | 2269 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); |
2270 | 2270 | } |
... | ... | @@ -3303,7 +3303,7 @@ |
3303 | 3303 | if ((error = xfs_btree_increment(cur, 0, &i))) |
3304 | 3304 | goto done; |
3305 | 3305 | cur->bc_rec.b = new; |
3306 | - error = xfs_bmbt_insert(cur, &i); | |
3306 | + error = xfs_btree_insert(cur, &i); | |
3307 | 3307 | if (error && error != ENOSPC) |
3308 | 3308 | goto done; |
3309 | 3309 | /* |
fs/xfs/xfs_bmap_btree.c
... | ... | @@ -456,198 +456,6 @@ |
456 | 456 | return error; |
457 | 457 | } |
458 | 458 | |
459 | -/* | |
460 | - * Insert one record/level. Return information to the caller | |
461 | - * allowing the next level up to proceed if necessary. | |
462 | - */ | |
463 | -STATIC int /* error */ | |
464 | -xfs_bmbt_insrec( | |
465 | - xfs_btree_cur_t *cur, | |
466 | - int level, | |
467 | - xfs_fsblock_t *bnop, | |
468 | - xfs_bmbt_rec_t *recp, | |
469 | - xfs_btree_cur_t **curp, | |
470 | - int *stat) /* no-go/done/continue */ | |
471 | -{ | |
472 | - xfs_bmbt_block_t *block; /* bmap btree block */ | |
473 | - xfs_buf_t *bp; /* buffer for block */ | |
474 | - int error; /* error return value */ | |
475 | - int i; /* loop index */ | |
476 | - xfs_bmbt_key_t key; /* bmap btree key */ | |
477 | - xfs_bmbt_key_t *kp=NULL; /* pointer to bmap btree key */ | |
478 | - int logflags; /* inode logging flags */ | |
479 | - xfs_fsblock_t nbno; /* new block number */ | |
480 | - struct xfs_btree_cur *ncur; /* new btree cursor */ | |
481 | - __uint64_t startoff; /* new btree key value */ | |
482 | - xfs_bmbt_rec_t nrec; /* new record count */ | |
483 | - int optr; /* old key/record index */ | |
484 | - xfs_bmbt_ptr_t *pp; /* pointer to bmap block addr */ | |
485 | - int ptr; /* key/record index */ | |
486 | - xfs_bmbt_rec_t *rp=NULL; /* pointer to bmap btree rec */ | |
487 | - int numrecs; | |
488 | - | |
489 | - ASSERT(level < cur->bc_nlevels); | |
490 | - XFS_BMBT_TRACE_CURSOR(cur, ENTRY); | |
491 | - XFS_BMBT_TRACE_ARGIFR(cur, level, *bnop, recp); | |
492 | - ncur = NULL; | |
493 | - key.br_startoff = cpu_to_be64(xfs_bmbt_disk_get_startoff(recp)); | |
494 | - optr = ptr = cur->bc_ptrs[level]; | |
495 | - if (ptr == 0) { | |
496 | - XFS_BMBT_TRACE_CURSOR(cur, EXIT); | |
497 | - *stat = 0; | |
498 | - return 0; | |
499 | - } | |
500 | - XFS_STATS_INC(xs_bmbt_insrec); | |
501 | - block = xfs_bmbt_get_block(cur, level, &bp); | |
502 | - numrecs = be16_to_cpu(block->bb_numrecs); | |
503 | -#ifdef DEBUG | |
504 | - if ((error = xfs_btree_check_lblock(cur, block, level, bp))) { | |
505 | - XFS_BMBT_TRACE_CURSOR(cur, ERROR); | |
506 | - return error; | |
507 | - } | |
508 | - if (ptr <= numrecs) { | |
509 | - if (level == 0) { | |
510 | - rp = XFS_BMAP_REC_IADDR(block, ptr, cur); | |
511 | - xfs_btree_check_rec(XFS_BTNUM_BMAP, recp, rp); | |
512 | - } else { | |
513 | - kp = XFS_BMAP_KEY_IADDR(block, ptr, cur); | |
514 | - xfs_btree_check_key(XFS_BTNUM_BMAP, &key, kp); | |
515 | - } | |
516 | - } | |
517 | -#endif | |
518 | - nbno = NULLFSBLOCK; | |
519 | - if (numrecs == XFS_BMAP_BLOCK_IMAXRECS(level, cur)) { | |
520 | - if (numrecs < XFS_BMAP_BLOCK_DMAXRECS(level, cur)) { | |
521 | - /* | |
522 | - * A root block, that can be made bigger. | |
523 | - */ | |
524 | - xfs_iroot_realloc(cur->bc_private.b.ip, 1, | |
525 | - cur->bc_private.b.whichfork); | |
526 | - block = xfs_bmbt_get_block(cur, level, &bp); | |
527 | - } else if (level == cur->bc_nlevels - 1) { | |
528 | - if ((error = xfs_btree_new_iroot(cur, &logflags, stat)) || | |
529 | - *stat == 0) { | |
530 | - XFS_BMBT_TRACE_CURSOR(cur, ERROR); | |
531 | - return error; | |
532 | - } | |
533 | - xfs_trans_log_inode(cur->bc_tp, cur->bc_private.b.ip, | |
534 | - logflags); | |
535 | - block = xfs_bmbt_get_block(cur, level, &bp); | |
536 | - } else { | |
537 | - if ((error = xfs_btree_rshift(cur, level, &i))) { | |
538 | - XFS_BMBT_TRACE_CURSOR(cur, ERROR); | |
539 | - return error; | |
540 | - } | |
541 | - if (i) { | |
542 | - /* nothing */ | |
543 | - } else { | |
544 | - if ((error = xfs_btree_lshift(cur, level, &i))) { | |
545 | - XFS_BMBT_TRACE_CURSOR(cur, ERROR); | |
546 | - return error; | |
547 | - } | |
548 | - if (i) { | |
549 | - optr = ptr = cur->bc_ptrs[level]; | |
550 | - } else { | |
551 | - union xfs_btree_ptr bno = { .l = cpu_to_be64(nbno) }; | |
552 | - union xfs_btree_key skey; | |
553 | - if ((error = xfs_btree_split(cur, level, | |
554 | - &bno, &skey, &ncur, | |
555 | - &i))) { | |
556 | - XFS_BMBT_TRACE_CURSOR(cur, | |
557 | - ERROR); | |
558 | - return error; | |
559 | - } | |
560 | - nbno = be64_to_cpu(bno.l); | |
561 | - startoff = be64_to_cpu(skey.bmbt.br_startoff); | |
562 | - if (i) { | |
563 | - block = xfs_bmbt_get_block( | |
564 | - cur, level, &bp); | |
565 | -#ifdef DEBUG | |
566 | - if ((error = | |
567 | - xfs_btree_check_lblock(cur, | |
568 | - block, level, bp))) { | |
569 | - XFS_BMBT_TRACE_CURSOR( | |
570 | - cur, ERROR); | |
571 | - return error; | |
572 | - } | |
573 | -#endif | |
574 | - ptr = cur->bc_ptrs[level]; | |
575 | - xfs_bmbt_disk_set_allf(&nrec, | |
576 | - startoff, 0, 0, | |
577 | - XFS_EXT_NORM); | |
578 | - } else { | |
579 | - XFS_BMBT_TRACE_CURSOR(cur, | |
580 | - EXIT); | |
581 | - *stat = 0; | |
582 | - return 0; | |
583 | - } | |
584 | - } | |
585 | - } | |
586 | - } | |
587 | - } | |
588 | - numrecs = be16_to_cpu(block->bb_numrecs); | |
589 | - if (level > 0) { | |
590 | - kp = XFS_BMAP_KEY_IADDR(block, 1, cur); | |
591 | - pp = XFS_BMAP_PTR_IADDR(block, 1, cur); | |
592 | -#ifdef DEBUG | |
593 | - for (i = numrecs; i >= ptr; i--) { | |
594 | - if ((error = xfs_btree_check_lptr_disk(cur, pp[i - 1], | |
595 | - level))) { | |
596 | - XFS_BMBT_TRACE_CURSOR(cur, ERROR); | |
597 | - return error; | |
598 | - } | |
599 | - } | |
600 | -#endif | |
601 | - memmove(&kp[ptr], &kp[ptr - 1], | |
602 | - (numrecs - ptr + 1) * sizeof(*kp)); | |
603 | - memmove(&pp[ptr], &pp[ptr - 1], | |
604 | - (numrecs - ptr + 1) * sizeof(*pp)); | |
605 | -#ifdef DEBUG | |
606 | - if ((error = xfs_btree_check_lptr(cur, *bnop, level))) { | |
607 | - XFS_BMBT_TRACE_CURSOR(cur, ERROR); | |
608 | - return error; | |
609 | - } | |
610 | -#endif | |
611 | - kp[ptr - 1] = key; | |
612 | - pp[ptr - 1] = cpu_to_be64(*bnop); | |
613 | - numrecs++; | |
614 | - block->bb_numrecs = cpu_to_be16(numrecs); | |
615 | - xfs_bmbt_log_keys(cur, bp, ptr, numrecs); | |
616 | - xfs_bmbt_log_ptrs(cur, bp, ptr, numrecs); | |
617 | - } else { | |
618 | - rp = XFS_BMAP_REC_IADDR(block, 1, cur); | |
619 | - memmove(&rp[ptr], &rp[ptr - 1], | |
620 | - (numrecs - ptr + 1) * sizeof(*rp)); | |
621 | - rp[ptr - 1] = *recp; | |
622 | - numrecs++; | |
623 | - block->bb_numrecs = cpu_to_be16(numrecs); | |
624 | - xfs_bmbt_log_recs(cur, bp, ptr, numrecs); | |
625 | - } | |
626 | - xfs_bmbt_log_block(cur, bp, XFS_BB_NUMRECS); | |
627 | -#ifdef DEBUG | |
628 | - if (ptr < numrecs) { | |
629 | - if (level == 0) | |
630 | - xfs_btree_check_rec(XFS_BTNUM_BMAP, rp + ptr - 1, | |
631 | - rp + ptr); | |
632 | - else | |
633 | - xfs_btree_check_key(XFS_BTNUM_BMAP, kp + ptr - 1, | |
634 | - kp + ptr); | |
635 | - } | |
636 | -#endif | |
637 | - if (optr == 1 && (error = xfs_btree_updkey(cur, (union xfs_btree_key *)&key, level + 1))) { | |
638 | - XFS_BMBT_TRACE_CURSOR(cur, ERROR); | |
639 | - return error; | |
640 | - } | |
641 | - *bnop = nbno; | |
642 | - if (nbno != NULLFSBLOCK) { | |
643 | - *recp = nrec; | |
644 | - *curp = ncur; | |
645 | - } | |
646 | - XFS_BMBT_TRACE_CURSOR(cur, EXIT); | |
647 | - *stat = 1; | |
648 | - return 0; | |
649 | -} | |
650 | - | |
651 | 459 | STATIC int |
652 | 460 | xfs_bmbt_killroot( |
653 | 461 | xfs_btree_cur_t *cur) |
... | ... | @@ -1060,67 +868,6 @@ |
1060 | 868 | } |
1061 | 869 | |
1062 | 870 | /* |
1063 | - * Insert the current record at the point referenced by cur. | |
1064 | - * | |
1065 | - * A multi-level split of the tree on insert will invalidate the original | |
1066 | - * cursor. All callers of this function should assume that the cursor is | |
1067 | - * no longer valid and revalidate it. | |
1068 | - */ | |
1069 | -int /* error */ | |
1070 | -xfs_bmbt_insert( | |
1071 | - xfs_btree_cur_t *cur, | |
1072 | - int *stat) /* success/failure */ | |
1073 | -{ | |
1074 | - int error; /* error return value */ | |
1075 | - int i; | |
1076 | - int level; | |
1077 | - xfs_fsblock_t nbno; | |
1078 | - xfs_btree_cur_t *ncur; | |
1079 | - xfs_bmbt_rec_t nrec; | |
1080 | - xfs_btree_cur_t *pcur; | |
1081 | - | |
1082 | - XFS_BMBT_TRACE_CURSOR(cur, ENTRY); | |
1083 | - level = 0; | |
1084 | - nbno = NULLFSBLOCK; | |
1085 | - xfs_bmbt_disk_set_all(&nrec, &cur->bc_rec.b); | |
1086 | - ncur = NULL; | |
1087 | - pcur = cur; | |
1088 | - do { | |
1089 | - if ((error = xfs_bmbt_insrec(pcur, level++, &nbno, &nrec, &ncur, | |
1090 | - &i))) { | |
1091 | - if (pcur != cur) | |
1092 | - xfs_btree_del_cursor(pcur, XFS_BTREE_ERROR); | |
1093 | - XFS_BMBT_TRACE_CURSOR(cur, ERROR); | |
1094 | - return error; | |
1095 | - } | |
1096 | - XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | |
1097 | - if (pcur != cur && (ncur || nbno == NULLFSBLOCK)) { | |
1098 | - cur->bc_nlevels = pcur->bc_nlevels; | |
1099 | - cur->bc_private.b.allocated += | |
1100 | - pcur->bc_private.b.allocated; | |
1101 | - pcur->bc_private.b.allocated = 0; | |
1102 | - ASSERT((cur->bc_private.b.firstblock != NULLFSBLOCK) || | |
1103 | - XFS_IS_REALTIME_INODE(cur->bc_private.b.ip)); | |
1104 | - cur->bc_private.b.firstblock = | |
1105 | - pcur->bc_private.b.firstblock; | |
1106 | - ASSERT(cur->bc_private.b.flist == | |
1107 | - pcur->bc_private.b.flist); | |
1108 | - xfs_btree_del_cursor(pcur, XFS_BTREE_NOERROR); | |
1109 | - } | |
1110 | - if (ncur) { | |
1111 | - pcur = ncur; | |
1112 | - ncur = NULL; | |
1113 | - } | |
1114 | - } while (nbno != NULLFSBLOCK); | |
1115 | - XFS_BMBT_TRACE_CURSOR(cur, EXIT); | |
1116 | - *stat = i; | |
1117 | - return 0; | |
1118 | -error0: | |
1119 | - XFS_BMBT_TRACE_CURSOR(cur, ERROR); | |
1120 | - return error; | |
1121 | -} | |
1122 | - | |
1123 | -/* | |
1124 | 871 | * Log fields from the btree block header. |
1125 | 872 | */ |
1126 | 873 | void |
... | ... | @@ -1450,6 +1197,21 @@ |
1450 | 1197 | return new; |
1451 | 1198 | } |
1452 | 1199 | |
1200 | +STATIC void | |
1201 | +xfs_bmbt_update_cursor( | |
1202 | + struct xfs_btree_cur *src, | |
1203 | + struct xfs_btree_cur *dst) | |
1204 | +{ | |
1205 | + ASSERT((dst->bc_private.b.firstblock != NULLFSBLOCK) || | |
1206 | + (dst->bc_private.b.ip->i_d.di_flags & XFS_DIFLAG_REALTIME)); | |
1207 | + ASSERT(dst->bc_private.b.flist == src->bc_private.b.flist); | |
1208 | + | |
1209 | + dst->bc_private.b.allocated += src->bc_private.b.allocated; | |
1210 | + dst->bc_private.b.firstblock = src->bc_private.b.firstblock; | |
1211 | + | |
1212 | + src->bc_private.b.allocated = 0; | |
1213 | +} | |
1214 | + | |
1453 | 1215 | STATIC int |
1454 | 1216 | xfs_bmbt_alloc_block( |
1455 | 1217 | struct xfs_btree_cur *cur, |
... | ... | @@ -1544,6 +1306,23 @@ |
1544 | 1306 | return XFS_BMAP_BLOCK_IMAXRECS(level, cur); |
1545 | 1307 | } |
1546 | 1308 | |
1309 | +/* | |
1310 | + * Get the maximum records we could store in the on-disk format. | |
1311 | + * | |
1312 | + * For non-root nodes this is equivalent to xfs_bmbt_get_maxrecs, but | |
1313 | + * for the root node this checks the available space in the dinode fork | |
1314 | + * so that we can resize the in-memory buffer to match it. After a | |
1315 | + * resize to the maximum size this function returns the same value | |
1316 | + * as xfs_bmbt_get_maxrecs for the root node, too. | |
1317 | + */ | |
1318 | +STATIC int | |
1319 | +xfs_bmbt_get_dmaxrecs( | |
1320 | + struct xfs_btree_cur *cur, | |
1321 | + int level) | |
1322 | +{ | |
1323 | + return XFS_BMAP_BLOCK_DMAXRECS(level, cur); | |
1324 | +} | |
1325 | + | |
1547 | 1326 | STATIC void |
1548 | 1327 | xfs_bmbt_init_key_from_rec( |
1549 | 1328 | union xfs_btree_key *key, |
... | ... | @@ -1554,6 +1333,25 @@ |
1554 | 1333 | } |
1555 | 1334 | |
1556 | 1335 | STATIC void |
1336 | +xfs_bmbt_init_rec_from_key( | |
1337 | + union xfs_btree_key *key, | |
1338 | + union xfs_btree_rec *rec) | |
1339 | +{ | |
1340 | + ASSERT(key->bmbt.br_startoff != 0); | |
1341 | + | |
1342 | + xfs_bmbt_disk_set_allf(&rec->bmbt, be64_to_cpu(key->bmbt.br_startoff), | |
1343 | + 0, 0, XFS_EXT_NORM); | |
1344 | +} | |
1345 | + | |
1346 | +STATIC void | |
1347 | +xfs_bmbt_init_rec_from_cur( | |
1348 | + struct xfs_btree_cur *cur, | |
1349 | + union xfs_btree_rec *rec) | |
1350 | +{ | |
1351 | + xfs_bmbt_disk_set_all(&rec->bmbt, &cur->bc_rec.b); | |
1352 | +} | |
1353 | + | |
1354 | +STATIC void | |
1557 | 1355 | xfs_bmbt_init_ptr_from_cur( |
1558 | 1356 | struct xfs_btree_cur *cur, |
1559 | 1357 | union xfs_btree_ptr *ptr) |
1560 | 1358 | |
1561 | 1359 | |
... | ... | @@ -1660,9 +1458,13 @@ |
1660 | 1458 | .key_len = sizeof(xfs_bmbt_key_t), |
1661 | 1459 | |
1662 | 1460 | .dup_cursor = xfs_bmbt_dup_cursor, |
1461 | + .update_cursor = xfs_bmbt_update_cursor, | |
1663 | 1462 | .alloc_block = xfs_bmbt_alloc_block, |
1664 | 1463 | .get_maxrecs = xfs_bmbt_get_maxrecs, |
1464 | + .get_dmaxrecs = xfs_bmbt_get_dmaxrecs, | |
1665 | 1465 | .init_key_from_rec = xfs_bmbt_init_key_from_rec, |
1466 | + .init_rec_from_key = xfs_bmbt_init_rec_from_key, | |
1467 | + .init_rec_from_cur = xfs_bmbt_init_rec_from_cur, | |
1666 | 1468 | .init_ptr_from_cur = xfs_bmbt_init_ptr_from_cur, |
1667 | 1469 | .key_diff = xfs_bmbt_key_diff, |
1668 | 1470 |
fs/xfs/xfs_bmap_btree.h
... | ... | @@ -250,7 +250,6 @@ |
250 | 250 | extern xfs_filblks_t xfs_bmbt_disk_get_blockcount(xfs_bmbt_rec_t *r); |
251 | 251 | extern xfs_fileoff_t xfs_bmbt_disk_get_startoff(xfs_bmbt_rec_t *r); |
252 | 252 | |
253 | -extern int xfs_bmbt_insert(struct xfs_btree_cur *, int *); | |
254 | 253 | extern void xfs_bmbt_log_block(struct xfs_btree_cur *, struct xfs_buf *, int); |
255 | 254 | extern void xfs_bmbt_log_recs(struct xfs_btree_cur *, struct xfs_buf *, int, |
256 | 255 | int); |
fs/xfs/xfs_btree.c
... | ... | @@ -963,6 +963,17 @@ |
963 | 963 | return be32_to_cpu(ptr->s) == NULLAGBLOCK; |
964 | 964 | } |
965 | 965 | |
966 | +STATIC void | |
967 | +xfs_btree_set_ptr_null( | |
968 | + struct xfs_btree_cur *cur, | |
969 | + union xfs_btree_ptr *ptr) | |
970 | +{ | |
971 | + if (cur->bc_flags & XFS_BTREE_LONG_PTRS) | |
972 | + ptr->l = cpu_to_be64(NULLFSBLOCK); | |
973 | + else | |
974 | + ptr->s = cpu_to_be32(NULLAGBLOCK); | |
975 | +} | |
976 | + | |
966 | 977 | /* |
967 | 978 | * Get/set/init sibling pointers |
968 | 979 | */ |
... | ... | @@ -2696,5 +2707,356 @@ |
2696 | 2707 | XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); |
2697 | 2708 | *stat = 0; |
2698 | 2709 | return 0; |
2710 | +} | |
2711 | + | |
2712 | +STATIC int | |
2713 | +xfs_btree_make_block_unfull( | |
2714 | + struct xfs_btree_cur *cur, /* btree cursor */ | |
2715 | + int level, /* btree level */ | |
2716 | + int numrecs,/* # of recs in block */ | |
2717 | + int *oindex,/* old tree index */ | |
2718 | + int *index, /* new tree index */ | |
2719 | + union xfs_btree_ptr *nptr, /* new btree ptr */ | |
2720 | + struct xfs_btree_cur **ncur, /* new btree cursor */ | |
2721 | + union xfs_btree_rec *nrec, /* new record */ | |
2722 | + int *stat) | |
2723 | +{ | |
2724 | + union xfs_btree_key key; /* new btree key value */ | |
2725 | + int error = 0; | |
2726 | + | |
2727 | + if ((cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) && | |
2728 | + level == cur->bc_nlevels - 1) { | |
2729 | + struct xfs_inode *ip = cur->bc_private.b.ip; | |
2730 | + | |
2731 | + if (numrecs < cur->bc_ops->get_dmaxrecs(cur, level)) { | |
2732 | + /* A root block that can be made bigger. */ | |
2733 | + | |
2734 | + xfs_iroot_realloc(ip, 1, cur->bc_private.b.whichfork); | |
2735 | + } else { | |
2736 | + /* A root block that needs replacing */ | |
2737 | + int logflags = 0; | |
2738 | + | |
2739 | + error = xfs_btree_new_iroot(cur, &logflags, stat); | |
2740 | + if (error || *stat == 0) | |
2741 | + return error; | |
2742 | + | |
2743 | + xfs_trans_log_inode(cur->bc_tp, ip, logflags); | |
2744 | + } | |
2745 | + | |
2746 | + return 0; | |
2747 | + } | |
2748 | + | |
2749 | + /* First, try shifting an entry to the right neighbor. */ | |
2750 | + error = xfs_btree_rshift(cur, level, stat); | |
2751 | + if (error || *stat) | |
2752 | + return error; | |
2753 | + | |
2754 | + /* Next, try shifting an entry to the left neighbor. */ | |
2755 | + error = xfs_btree_lshift(cur, level, stat); | |
2756 | + if (error) | |
2757 | + return error; | |
2758 | + | |
2759 | + if (*stat) { | |
2760 | + *oindex = *index = cur->bc_ptrs[level]; | |
2761 | + return 0; | |
2762 | + } | |
2763 | + | |
2764 | + /* | |
2765 | + * Next, try splitting the current block in half. | |
2766 | + * | |
2767 | + * If this works we have to re-set our variables because we | |
2768 | + * could be in a different block now. | |
2769 | + */ | |
2770 | + error = xfs_btree_split(cur, level, nptr, &key, ncur, stat); | |
2771 | + if (error || *stat == 0) | |
2772 | + return error; | |
2773 | + | |
2774 | + | |
2775 | + *index = cur->bc_ptrs[level]; | |
2776 | + cur->bc_ops->init_rec_from_key(&key, nrec); | |
2777 | + return 0; | |
2778 | +} | |
2779 | + | |
2780 | +/* | |
2781 | + * Insert one record/level. Return information to the caller | |
2782 | + * allowing the next level up to proceed if necessary. | |
2783 | + */ | |
2784 | +STATIC int | |
2785 | +xfs_btree_insrec( | |
2786 | + struct xfs_btree_cur *cur, /* btree cursor */ | |
2787 | + int level, /* level to insert record at */ | |
2788 | + union xfs_btree_ptr *ptrp, /* i/o: block number inserted */ | |
2789 | + union xfs_btree_rec *recp, /* i/o: record data inserted */ | |
2790 | + struct xfs_btree_cur **curp, /* output: new cursor replacing cur */ | |
2791 | + int *stat) /* success/failure */ | |
2792 | +{ | |
2793 | + struct xfs_btree_block *block; /* btree block */ | |
2794 | + struct xfs_buf *bp; /* buffer for block */ | |
2795 | + union xfs_btree_key key; /* btree key */ | |
2796 | + union xfs_btree_ptr nptr; /* new block ptr */ | |
2797 | + struct xfs_btree_cur *ncur; /* new btree cursor */ | |
2798 | + union xfs_btree_rec nrec; /* new record count */ | |
2799 | + int optr; /* old key/record index */ | |
2800 | + int ptr; /* key/record index */ | |
2801 | + int numrecs;/* number of records */ | |
2802 | + int error; /* error return value */ | |
2803 | +#ifdef DEBUG | |
2804 | + int i; | |
2805 | +#endif | |
2806 | + | |
2807 | + XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); | |
2808 | + XFS_BTREE_TRACE_ARGIPR(cur, level, *ptrp, recp); | |
2809 | + | |
2810 | + ncur = NULL; | |
2811 | + | |
2812 | + /* | |
2813 | + * If we have an external root pointer, and we've made it to the | |
2814 | + * root level, allocate a new root block and we're done. | |
2815 | + */ | |
2816 | + if (!(cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) && | |
2817 | + (level >= cur->bc_nlevels)) { | |
2818 | + error = xfs_btree_new_root(cur, stat); | |
2819 | + xfs_btree_set_ptr_null(cur, ptrp); | |
2820 | + | |
2821 | + XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); | |
2822 | + return error; | |
2823 | + } | |
2824 | + | |
2825 | + /* If we're off the left edge, return failure. */ | |
2826 | + ptr = cur->bc_ptrs[level]; | |
2827 | + if (ptr == 0) { | |
2828 | + XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); | |
2829 | + *stat = 0; | |
2830 | + return 0; | |
2831 | + } | |
2832 | + | |
2833 | + /* Make a key out of the record data to be inserted, and save it. */ | |
2834 | + cur->bc_ops->init_key_from_rec(&key, recp); | |
2835 | + | |
2836 | + optr = ptr; | |
2837 | + | |
2838 | + XFS_BTREE_STATS_INC(cur, insrec); | |
2839 | + | |
2840 | + /* Get pointers to the btree buffer and block. */ | |
2841 | + block = xfs_btree_get_block(cur, level, &bp); | |
2842 | + numrecs = xfs_btree_get_numrecs(block); | |
2843 | + | |
2844 | +#ifdef DEBUG | |
2845 | + error = xfs_btree_check_block(cur, block, level, bp); | |
2846 | + if (error) | |
2847 | + goto error0; | |
2848 | + | |
2849 | + /* Check that the new entry is being inserted in the right place. */ | |
2850 | + if (ptr <= numrecs) { | |
2851 | + if (level == 0) { | |
2852 | + xfs_btree_check_rec(cur->bc_btnum, recp, | |
2853 | + xfs_btree_rec_addr(cur, ptr, block)); | |
2854 | + } else { | |
2855 | + xfs_btree_check_key(cur->bc_btnum, &key, | |
2856 | + xfs_btree_key_addr(cur, ptr, block)); | |
2857 | + } | |
2858 | + } | |
2859 | +#endif | |
2860 | + | |
2861 | + /* | |
2862 | + * If the block is full, we can't insert the new entry until we | |
2863 | + * make the block un-full. | |
2864 | + */ | |
2865 | + xfs_btree_set_ptr_null(cur, &nptr); | |
2866 | + if (numrecs == cur->bc_ops->get_maxrecs(cur, level)) { | |
2867 | + error = xfs_btree_make_block_unfull(cur, level, numrecs, | |
2868 | + &optr, &ptr, &nptr, &ncur, &nrec, stat); | |
2869 | + if (error || *stat == 0) | |
2870 | + goto error0; | |
2871 | + } | |
2872 | + | |
2873 | + /* | |
2874 | + * The current block may have changed if the block was | |
2875 | + * previously full and we have just made space in it. | |
2876 | + */ | |
2877 | + block = xfs_btree_get_block(cur, level, &bp); | |
2878 | + numrecs = xfs_btree_get_numrecs(block); | |
2879 | + | |
2880 | +#ifdef DEBUG | |
2881 | + error = xfs_btree_check_block(cur, block, level, bp); | |
2882 | + if (error) | |
2883 | + return error; | |
2884 | +#endif | |
2885 | + | |
2886 | + /* | |
2887 | + * At this point we know there's room for our new entry in the block | |
2888 | + * we're pointing at. | |
2889 | + */ | |
2890 | + XFS_BTREE_STATS_ADD(cur, moves, numrecs - ptr + 1); | |
2891 | + | |
2892 | + if (level > 0) { | |
2893 | + /* It's a nonleaf. make a hole in the keys and ptrs */ | |
2894 | + union xfs_btree_key *kp; | |
2895 | + union xfs_btree_ptr *pp; | |
2896 | + | |
2897 | + kp = xfs_btree_key_addr(cur, ptr, block); | |
2898 | + pp = xfs_btree_ptr_addr(cur, ptr, block); | |
2899 | + | |
2900 | +#ifdef DEBUG | |
2901 | + for (i = numrecs - ptr; i >= 0; i--) { | |
2902 | + error = xfs_btree_check_ptr(cur, pp, i, level); | |
2903 | + if (error) | |
2904 | + return error; | |
2905 | + } | |
2906 | +#endif | |
2907 | + | |
2908 | + xfs_btree_shift_keys(cur, kp, 1, numrecs - ptr + 1); | |
2909 | + xfs_btree_shift_ptrs(cur, pp, 1, numrecs - ptr + 1); | |
2910 | + | |
2911 | +#ifdef DEBUG | |
2912 | + error = xfs_btree_check_ptr(cur, ptrp, 0, level); | |
2913 | + if (error) | |
2914 | + goto error0; | |
2915 | +#endif | |
2916 | + | |
2917 | + /* Now put the new data in, bump numrecs and log it. */ | |
2918 | + xfs_btree_copy_keys(cur, kp, &key, 1); | |
2919 | + xfs_btree_copy_ptrs(cur, pp, ptrp, 1); | |
2920 | + numrecs++; | |
2921 | + xfs_btree_set_numrecs(block, numrecs); | |
2922 | + xfs_btree_log_ptrs(cur, bp, ptr, numrecs); | |
2923 | + xfs_btree_log_keys(cur, bp, ptr, numrecs); | |
2924 | +#ifdef DEBUG | |
2925 | + if (ptr < numrecs) { | |
2926 | + xfs_btree_check_key(cur->bc_btnum, kp, | |
2927 | + xfs_btree_key_addr(cur, ptr + 1, block)); | |
2928 | + } | |
2929 | +#endif | |
2930 | + } else { | |
2931 | + /* It's a leaf. make a hole in the records */ | |
2932 | + union xfs_btree_rec *rp; | |
2933 | + | |
2934 | + rp = xfs_btree_rec_addr(cur, ptr, block); | |
2935 | + | |
2936 | + xfs_btree_shift_recs(cur, rp, 1, numrecs - ptr + 1); | |
2937 | + | |
2938 | + /* Now put the new data in, bump numrecs and log it. */ | |
2939 | + xfs_btree_copy_recs(cur, rp, recp, 1); | |
2940 | + xfs_btree_set_numrecs(block, ++numrecs); | |
2941 | + xfs_btree_log_recs(cur, bp, ptr, numrecs); | |
2942 | +#ifdef DEBUG | |
2943 | + if (ptr < numrecs) { | |
2944 | + xfs_btree_check_rec(cur->bc_btnum, rp, | |
2945 | + xfs_btree_rec_addr(cur, ptr + 1, block)); | |
2946 | + } | |
2947 | +#endif | |
2948 | + } | |
2949 | + | |
2950 | + /* Log the new number of records in the btree header. */ | |
2951 | + xfs_btree_log_block(cur, bp, XFS_BB_NUMRECS); | |
2952 | + | |
2953 | + /* If we inserted at the start of a block, update the parents' keys. */ | |
2954 | + if (optr == 1) { | |
2955 | + error = xfs_btree_updkey(cur, &key, level + 1); | |
2956 | + if (error) | |
2957 | + goto error0; | |
2958 | + } | |
2959 | + | |
2960 | + /* | |
2961 | + * If we are tracking the last record in the tree and | |
2962 | + * we are at the far right edge of the tree, update it. | |
2963 | + */ | |
2964 | + if (xfs_btree_is_lastrec(cur, block, level)) { | |
2965 | + cur->bc_ops->update_lastrec(cur, block, recp, | |
2966 | + ptr, LASTREC_INSREC); | |
2967 | + } | |
2968 | + | |
2969 | + /* | |
2970 | + * Return the new block number, if any. | |
2971 | + * If there is one, give back a record value and a cursor too. | |
2972 | + */ | |
2973 | + *ptrp = nptr; | |
2974 | + if (!xfs_btree_ptr_is_null(cur, &nptr)) { | |
2975 | + *recp = nrec; | |
2976 | + *curp = ncur; | |
2977 | + } | |
2978 | + | |
2979 | + XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); | |
2980 | + *stat = 1; | |
2981 | + return 0; | |
2982 | + | |
2983 | +error0: | |
2984 | + XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR); | |
2985 | + return error; | |
2986 | +} | |
2987 | + | |
2988 | +/* | |
2989 | + * Insert the record at the point referenced by cur. | |
2990 | + * | |
2991 | + * A multi-level split of the tree on insert will invalidate the original | |
2992 | + * cursor. All callers of this function should assume that the cursor is | |
2993 | + * no longer valid and revalidate it. | |
2994 | + */ | |
2995 | +int | |
2996 | +xfs_btree_insert( | |
2997 | + struct xfs_btree_cur *cur, | |
2998 | + int *stat) | |
2999 | +{ | |
3000 | + int error; /* error return value */ | |
3001 | + int i; /* result value, 0 for failure */ | |
3002 | + int level; /* current level number in btree */ | |
3003 | + union xfs_btree_ptr nptr; /* new block number (split result) */ | |
3004 | + struct xfs_btree_cur *ncur; /* new cursor (split result) */ | |
3005 | + struct xfs_btree_cur *pcur; /* previous level's cursor */ | |
3006 | + union xfs_btree_rec rec; /* record to insert */ | |
3007 | + | |
3008 | + level = 0; | |
3009 | + ncur = NULL; | |
3010 | + pcur = cur; | |
3011 | + | |
3012 | + xfs_btree_set_ptr_null(cur, &nptr); | |
3013 | + cur->bc_ops->init_rec_from_cur(cur, &rec); | |
3014 | + | |
3015 | + /* | |
3016 | + * Loop going up the tree, starting at the leaf level. | |
3017 | + * Stop when we don't get a split block, that must mean that | |
3018 | + * the insert is finished with this level. | |
3019 | + */ | |
3020 | + do { | |
3021 | + /* | |
3022 | + * Insert nrec/nptr into this level of the tree. | |
3023 | + * Note if we fail, nptr will be null. | |
3024 | + */ | |
3025 | + error = xfs_btree_insrec(pcur, level, &nptr, &rec, &ncur, &i); | |
3026 | + if (error) { | |
3027 | + if (pcur != cur) | |
3028 | + xfs_btree_del_cursor(pcur, XFS_BTREE_ERROR); | |
3029 | + goto error0; | |
3030 | + } | |
3031 | + | |
3032 | + XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | |
3033 | + level++; | |
3034 | + | |
3035 | + /* | |
3036 | + * See if the cursor we just used is trash. | |
3037 | + * Can't trash the caller's cursor, but otherwise we should | |
3038 | + * if ncur is a new cursor or we're about to be done. | |
3039 | + */ | |
3040 | + if (pcur != cur && | |
3041 | + (ncur || xfs_btree_ptr_is_null(cur, &nptr))) { | |
3042 | + /* Save the state from the cursor before we trash it */ | |
3043 | + if (cur->bc_ops->update_cursor) | |
3044 | + cur->bc_ops->update_cursor(pcur, cur); | |
3045 | + cur->bc_nlevels = pcur->bc_nlevels; | |
3046 | + xfs_btree_del_cursor(pcur, XFS_BTREE_NOERROR); | |
3047 | + } | |
3048 | + /* If we got a new cursor, switch to it. */ | |
3049 | + if (ncur) { | |
3050 | + pcur = ncur; | |
3051 | + ncur = NULL; | |
3052 | + } | |
3053 | + } while (!xfs_btree_ptr_is_null(cur, &nptr)); | |
3054 | + | |
3055 | + XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); | |
3056 | + *stat = i; | |
3057 | + return 0; | |
3058 | +error0: | |
3059 | + XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR); | |
3060 | + return error; | |
2699 | 3061 | } |
fs/xfs/xfs_btree.h
... | ... | @@ -186,6 +186,8 @@ |
186 | 186 | |
187 | 187 | /* cursor operations */ |
188 | 188 | struct xfs_btree_cur *(*dup_cursor)(struct xfs_btree_cur *); |
189 | + void (*update_cursor)(struct xfs_btree_cur *src, | |
190 | + struct xfs_btree_cur *dst); | |
189 | 191 | |
190 | 192 | /* update btree root pointer */ |
191 | 193 | void (*set_root)(struct xfs_btree_cur *cur, |
192 | 194 | |
... | ... | @@ -206,9 +208,16 @@ |
206 | 208 | /* records in block/level */ |
207 | 209 | int (*get_maxrecs)(struct xfs_btree_cur *cur, int level); |
208 | 210 | |
211 | + /* records on disk. Matter for the root in inode case. */ | |
212 | + int (*get_dmaxrecs)(struct xfs_btree_cur *cur, int level); | |
213 | + | |
209 | 214 | /* init values of btree structures */ |
210 | 215 | void (*init_key_from_rec)(union xfs_btree_key *key, |
211 | 216 | union xfs_btree_rec *rec); |
217 | + void (*init_rec_from_key)(union xfs_btree_key *key, | |
218 | + union xfs_btree_rec *rec); | |
219 | + void (*init_rec_from_cur)(struct xfs_btree_cur *cur, | |
220 | + union xfs_btree_rec *rec); | |
212 | 221 | void (*init_ptr_from_cur)(struct xfs_btree_cur *cur, |
213 | 222 | union xfs_btree_ptr *ptr); |
214 | 223 | |
... | ... | @@ -240,6 +249,7 @@ |
240 | 249 | * Reasons for the update_lastrec method to be called. |
241 | 250 | */ |
242 | 251 | #define LASTREC_UPDATE 0 |
252 | +#define LASTREC_INSREC 1 | |
243 | 253 | |
244 | 254 | |
245 | 255 | /* |
... | ... | @@ -549,6 +559,7 @@ |
549 | 559 | union xfs_btree_key *, struct xfs_btree_cur **, int *); |
550 | 560 | int xfs_btree_new_root(struct xfs_btree_cur *, int *); |
551 | 561 | int xfs_btree_new_iroot(struct xfs_btree_cur *, int *, int *); |
562 | +int xfs_btree_insert(struct xfs_btree_cur *, int *); | |
552 | 563 | |
553 | 564 | /* |
554 | 565 | * Helpers. |
fs/xfs/xfs_ialloc.c
fs/xfs/xfs_ialloc_btree.c
... | ... | @@ -515,228 +515,6 @@ |
515 | 515 | } |
516 | 516 | |
517 | 517 | /* |
518 | - * Insert one record/level. Return information to the caller | |
519 | - * allowing the next level up to proceed if necessary. | |
520 | - */ | |
521 | -STATIC int /* error */ | |
522 | -xfs_inobt_insrec( | |
523 | - xfs_btree_cur_t *cur, /* btree cursor */ | |
524 | - int level, /* level to insert record at */ | |
525 | - xfs_agblock_t *bnop, /* i/o: block number inserted */ | |
526 | - xfs_inobt_rec_t *recp, /* i/o: record data inserted */ | |
527 | - xfs_btree_cur_t **curp, /* output: new cursor replacing cur */ | |
528 | - int *stat) /* success/failure */ | |
529 | -{ | |
530 | - xfs_inobt_block_t *block; /* btree block record/key lives in */ | |
531 | - xfs_buf_t *bp; /* buffer for block */ | |
532 | - int error; /* error return value */ | |
533 | - int i; /* loop index */ | |
534 | - xfs_inobt_key_t key; /* key value being inserted */ | |
535 | - xfs_inobt_key_t *kp=NULL; /* pointer to btree keys */ | |
536 | - xfs_agblock_t nbno; /* block number of allocated block */ | |
537 | - xfs_btree_cur_t *ncur; /* new cursor to be used at next lvl */ | |
538 | - xfs_inobt_key_t nkey; /* new key value, from split */ | |
539 | - xfs_inobt_rec_t nrec; /* new record value, for caller */ | |
540 | - int numrecs; | |
541 | - int optr; /* old ptr value */ | |
542 | - xfs_inobt_ptr_t *pp; /* pointer to btree addresses */ | |
543 | - int ptr; /* index in btree block for this rec */ | |
544 | - xfs_inobt_rec_t *rp=NULL; /* pointer to btree records */ | |
545 | - | |
546 | - /* | |
547 | - * GCC doesn't understand the (arguably complex) control flow in | |
548 | - * this function and complains about uninitialized structure fields | |
549 | - * without this. | |
550 | - */ | |
551 | - memset(&nrec, 0, sizeof(nrec)); | |
552 | - | |
553 | - /* | |
554 | - * If we made it to the root level, allocate a new root block | |
555 | - * and we're done. | |
556 | - */ | |
557 | - if (level >= cur->bc_nlevels) { | |
558 | - error = xfs_btree_new_root(cur, &i); | |
559 | - *bnop = NULLAGBLOCK; | |
560 | - *stat = i; | |
561 | - return error; | |
562 | - } | |
563 | - /* | |
564 | - * Make a key out of the record data to be inserted, and save it. | |
565 | - */ | |
566 | - key.ir_startino = recp->ir_startino; | |
567 | - optr = ptr = cur->bc_ptrs[level]; | |
568 | - /* | |
569 | - * If we're off the left edge, return failure. | |
570 | - */ | |
571 | - if (ptr == 0) { | |
572 | - *stat = 0; | |
573 | - return 0; | |
574 | - } | |
575 | - /* | |
576 | - * Get pointers to the btree buffer and block. | |
577 | - */ | |
578 | - bp = cur->bc_bufs[level]; | |
579 | - block = XFS_BUF_TO_INOBT_BLOCK(bp); | |
580 | - numrecs = be16_to_cpu(block->bb_numrecs); | |
581 | -#ifdef DEBUG | |
582 | - if ((error = xfs_btree_check_sblock(cur, block, level, bp))) | |
583 | - return error; | |
584 | - /* | |
585 | - * Check that the new entry is being inserted in the right place. | |
586 | - */ | |
587 | - if (ptr <= numrecs) { | |
588 | - if (level == 0) { | |
589 | - rp = XFS_INOBT_REC_ADDR(block, ptr, cur); | |
590 | - xfs_btree_check_rec(cur->bc_btnum, recp, rp); | |
591 | - } else { | |
592 | - kp = XFS_INOBT_KEY_ADDR(block, ptr, cur); | |
593 | - xfs_btree_check_key(cur->bc_btnum, &key, kp); | |
594 | - } | |
595 | - } | |
596 | -#endif | |
597 | - nbno = NULLAGBLOCK; | |
598 | - ncur = NULL; | |
599 | - /* | |
600 | - * If the block is full, we can't insert the new entry until we | |
601 | - * make the block un-full. | |
602 | - */ | |
603 | - if (numrecs == XFS_INOBT_BLOCK_MAXRECS(level, cur)) { | |
604 | - /* | |
605 | - * First, try shifting an entry to the right neighbor. | |
606 | - */ | |
607 | - if ((error = xfs_btree_rshift(cur, level, &i))) | |
608 | - return error; | |
609 | - if (i) { | |
610 | - /* nothing */ | |
611 | - } | |
612 | - /* | |
613 | - * Next, try shifting an entry to the left neighbor. | |
614 | - */ | |
615 | - else { | |
616 | - if ((error = xfs_btree_lshift(cur, level, &i))) | |
617 | - return error; | |
618 | - if (i) { | |
619 | - optr = ptr = cur->bc_ptrs[level]; | |
620 | - } else { | |
621 | - union xfs_btree_ptr bno = { .s = cpu_to_be32(nbno) }; | |
622 | - /* | |
623 | - * Next, try splitting the current block | |
624 | - * in half. If this works we have to | |
625 | - * re-set our variables because | |
626 | - * we could be in a different block now. | |
627 | - */ | |
628 | - if ((error = xfs_btree_split(cur, level, &bno, | |
629 | - (union xfs_btree_key *)&nkey, | |
630 | - &ncur, &i))) | |
631 | - return error; | |
632 | - nbno = be32_to_cpu(bno.s); | |
633 | - if (i) { | |
634 | - bp = cur->bc_bufs[level]; | |
635 | - block = XFS_BUF_TO_INOBT_BLOCK(bp); | |
636 | -#ifdef DEBUG | |
637 | - if ((error = xfs_btree_check_sblock(cur, | |
638 | - block, level, bp))) | |
639 | - return error; | |
640 | -#endif | |
641 | - ptr = cur->bc_ptrs[level]; | |
642 | - nrec.ir_startino = nkey.ir_startino; | |
643 | - } else { | |
644 | - /* | |
645 | - * Otherwise the insert fails. | |
646 | - */ | |
647 | - *stat = 0; | |
648 | - return 0; | |
649 | - } | |
650 | - } | |
651 | - } | |
652 | - } | |
653 | - /* | |
654 | - * At this point we know there's room for our new entry in the block | |
655 | - * we're pointing at. | |
656 | - */ | |
657 | - numrecs = be16_to_cpu(block->bb_numrecs); | |
658 | - if (level > 0) { | |
659 | - /* | |
660 | - * It's a non-leaf entry. Make a hole for the new data | |
661 | - * in the key and ptr regions of the block. | |
662 | - */ | |
663 | - kp = XFS_INOBT_KEY_ADDR(block, 1, cur); | |
664 | - pp = XFS_INOBT_PTR_ADDR(block, 1, cur); | |
665 | -#ifdef DEBUG | |
666 | - for (i = numrecs; i >= ptr; i--) { | |
667 | - if ((error = xfs_btree_check_sptr(cur, be32_to_cpu(pp[i - 1]), level))) | |
668 | - return error; | |
669 | - } | |
670 | -#endif | |
671 | - memmove(&kp[ptr], &kp[ptr - 1], | |
672 | - (numrecs - ptr + 1) * sizeof(*kp)); | |
673 | - memmove(&pp[ptr], &pp[ptr - 1], | |
674 | - (numrecs - ptr + 1) * sizeof(*pp)); | |
675 | - /* | |
676 | - * Now stuff the new data in, bump numrecs and log the new data. | |
677 | - */ | |
678 | -#ifdef DEBUG | |
679 | - if ((error = xfs_btree_check_sptr(cur, *bnop, level))) | |
680 | - return error; | |
681 | -#endif | |
682 | - kp[ptr - 1] = key; | |
683 | - pp[ptr - 1] = cpu_to_be32(*bnop); | |
684 | - numrecs++; | |
685 | - block->bb_numrecs = cpu_to_be16(numrecs); | |
686 | - xfs_inobt_log_keys(cur, bp, ptr, numrecs); | |
687 | - xfs_inobt_log_ptrs(cur, bp, ptr, numrecs); | |
688 | - } else { | |
689 | - /* | |
690 | - * It's a leaf entry. Make a hole for the new record. | |
691 | - */ | |
692 | - rp = XFS_INOBT_REC_ADDR(block, 1, cur); | |
693 | - memmove(&rp[ptr], &rp[ptr - 1], | |
694 | - (numrecs - ptr + 1) * sizeof(*rp)); | |
695 | - /* | |
696 | - * Now stuff the new record in, bump numrecs | |
697 | - * and log the new data. | |
698 | - */ | |
699 | - rp[ptr - 1] = *recp; | |
700 | - numrecs++; | |
701 | - block->bb_numrecs = cpu_to_be16(numrecs); | |
702 | - xfs_inobt_log_recs(cur, bp, ptr, numrecs); | |
703 | - } | |
704 | - /* | |
705 | - * Log the new number of records in the btree header. | |
706 | - */ | |
707 | - xfs_inobt_log_block(cur->bc_tp, bp, XFS_BB_NUMRECS); | |
708 | -#ifdef DEBUG | |
709 | - /* | |
710 | - * Check that the key/record is in the right place, now. | |
711 | - */ | |
712 | - if (ptr < numrecs) { | |
713 | - if (level == 0) | |
714 | - xfs_btree_check_rec(cur->bc_btnum, rp + ptr - 1, | |
715 | - rp + ptr); | |
716 | - else | |
717 | - xfs_btree_check_key(cur->bc_btnum, kp + ptr - 1, | |
718 | - kp + ptr); | |
719 | - } | |
720 | -#endif | |
721 | - /* | |
722 | - * If we inserted at the start of a block, update the parents' keys. | |
723 | - */ | |
724 | - if (optr == 1 && (error = xfs_btree_updkey(cur, (union xfs_btree_key *)&key, level + 1))) | |
725 | - return error; | |
726 | - /* | |
727 | - * Return the new block number, if any. | |
728 | - * If there is one, give back a record value and a cursor too. | |
729 | - */ | |
730 | - *bnop = nbno; | |
731 | - if (nbno != NULLAGBLOCK) { | |
732 | - *recp = nrec; | |
733 | - *curp = ncur; | |
734 | - } | |
735 | - *stat = 1; | |
736 | - return 0; | |
737 | -} | |
738 | - | |
739 | -/* | |
740 | 518 | * Log header fields from a btree block. |
741 | 519 | */ |
742 | 520 | STATIC void |
743 | 521 | |
... | ... | @@ -912,67 +690,7 @@ |
912 | 690 | return 0; |
913 | 691 | } |
914 | 692 | |
915 | -/* | |
916 | - * Insert the current record at the point referenced by cur. | |
917 | - * The cursor may be inconsistent on return if splits have been done. | |
918 | - */ | |
919 | -int /* error */ | |
920 | -xfs_inobt_insert( | |
921 | - xfs_btree_cur_t *cur, /* btree cursor */ | |
922 | - int *stat) /* success/failure */ | |
923 | -{ | |
924 | - int error; /* error return value */ | |
925 | - int i; /* result value, 0 for failure */ | |
926 | - int level; /* current level number in btree */ | |
927 | - xfs_agblock_t nbno; /* new block number (split result) */ | |
928 | - xfs_btree_cur_t *ncur; /* new cursor (split result) */ | |
929 | - xfs_inobt_rec_t nrec; /* record being inserted this level */ | |
930 | - xfs_btree_cur_t *pcur; /* previous level's cursor */ | |
931 | 693 | |
932 | - level = 0; | |
933 | - nbno = NULLAGBLOCK; | |
934 | - nrec.ir_startino = cpu_to_be32(cur->bc_rec.i.ir_startino); | |
935 | - nrec.ir_freecount = cpu_to_be32(cur->bc_rec.i.ir_freecount); | |
936 | - nrec.ir_free = cpu_to_be64(cur->bc_rec.i.ir_free); | |
937 | - ncur = NULL; | |
938 | - pcur = cur; | |
939 | - /* | |
940 | - * Loop going up the tree, starting at the leaf level. | |
941 | - * Stop when we don't get a split block, that must mean that | |
942 | - * the insert is finished with this level. | |
943 | - */ | |
944 | - do { | |
945 | - /* | |
946 | - * Insert nrec/nbno into this level of the tree. | |
947 | - * Note if we fail, nbno will be null. | |
948 | - */ | |
949 | - if ((error = xfs_inobt_insrec(pcur, level++, &nbno, &nrec, &ncur, | |
950 | - &i))) { | |
951 | - if (pcur != cur) | |
952 | - xfs_btree_del_cursor(pcur, XFS_BTREE_ERROR); | |
953 | - return error; | |
954 | - } | |
955 | - /* | |
956 | - * See if the cursor we just used is trash. | |
957 | - * Can't trash the caller's cursor, but otherwise we should | |
958 | - * if ncur is a new cursor or we're about to be done. | |
959 | - */ | |
960 | - if (pcur != cur && (ncur || nbno == NULLAGBLOCK)) { | |
961 | - cur->bc_nlevels = pcur->bc_nlevels; | |
962 | - xfs_btree_del_cursor(pcur, XFS_BTREE_NOERROR); | |
963 | - } | |
964 | - /* | |
965 | - * If we got a new cursor, switch to it. | |
966 | - */ | |
967 | - if (ncur) { | |
968 | - pcur = ncur; | |
969 | - ncur = NULL; | |
970 | - } | |
971 | - } while (nbno != NULLAGBLOCK); | |
972 | - *stat = i; | |
973 | - return 0; | |
974 | -} | |
975 | - | |
976 | 694 | STATIC struct xfs_btree_cur * |
977 | 695 | xfs_inobt_dup_cursor( |
978 | 696 | struct xfs_btree_cur *cur) |
... | ... | @@ -1053,6 +771,24 @@ |
1053 | 771 | key->inobt.ir_startino = rec->inobt.ir_startino; |
1054 | 772 | } |
1055 | 773 | |
774 | +STATIC void | |
775 | +xfs_inobt_init_rec_from_key( | |
776 | + union xfs_btree_key *key, | |
777 | + union xfs_btree_rec *rec) | |
778 | +{ | |
779 | + rec->inobt.ir_startino = key->inobt.ir_startino; | |
780 | +} | |
781 | + | |
782 | +STATIC void | |
783 | +xfs_inobt_init_rec_from_cur( | |
784 | + struct xfs_btree_cur *cur, | |
785 | + union xfs_btree_rec *rec) | |
786 | +{ | |
787 | + rec->inobt.ir_startino = cpu_to_be32(cur->bc_rec.i.ir_startino); | |
788 | + rec->inobt.ir_freecount = cpu_to_be32(cur->bc_rec.i.ir_freecount); | |
789 | + rec->inobt.ir_free = cpu_to_be64(cur->bc_rec.i.ir_free); | |
790 | +} | |
791 | + | |
1056 | 792 | /* |
1057 | 793 | * intial value of ptr for lookup |
1058 | 794 | */ |
... | ... | @@ -1152,6 +888,8 @@ |
1152 | 888 | .alloc_block = xfs_inobt_alloc_block, |
1153 | 889 | .get_maxrecs = xfs_inobt_get_maxrecs, |
1154 | 890 | .init_key_from_rec = xfs_inobt_init_key_from_rec, |
891 | + .init_rec_from_key = xfs_inobt_init_rec_from_key, | |
892 | + .init_rec_from_cur = xfs_inobt_init_rec_from_cur, | |
1155 | 893 | .init_ptr_from_cur = xfs_inobt_init_ptr_from_cur, |
1156 | 894 | .key_diff = xfs_inobt_key_diff, |
1157 | 895 |
fs/xfs/xfs_ialloc_btree.h
... | ... | @@ -129,12 +129,6 @@ |
129 | 129 | extern int xfs_inobt_get_rec(struct xfs_btree_cur *cur, xfs_agino_t *ino, |
130 | 130 | __int32_t *fcnt, xfs_inofree_t *free, int *stat); |
131 | 131 | |
132 | -/* | |
133 | - * Insert the current record at the point referenced by cur. | |
134 | - * The cursor may be inconsistent on return if splits have been done. | |
135 | - */ | |
136 | -extern int xfs_inobt_insert(struct xfs_btree_cur *cur, int *stat); | |
137 | - | |
138 | 132 | |
139 | 133 | extern struct xfs_btree_cur *xfs_inobt_init_cursor(struct xfs_mount *, |
140 | 134 | struct xfs_trans *, struct xfs_buf *, xfs_agnumber_t); |