Commit 4b22a57188d87e873346b73c227607715be96399

Authored by Christoph Hellwig
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

... ... @@ -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 *,
... ... @@ -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);
... ... @@ -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 }
... ... @@ -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.
... ... @@ -418,7 +418,7 @@
418 418 return error;
419 419 }
420 420 ASSERT(i == 0);
421   - if ((error = xfs_inobt_insert(cur, &i))) {
  421 + if ((error = xfs_btree_insert(cur, &i))) {
422 422 xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
423 423 return error;
424 424 }
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);