1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18#include "xfs.h"
19#include "xfs_fs.h"
20#include "xfs_types.h"
21#include "xfs_bit.h"
22#include "xfs_log.h"
23#include "xfs_inum.h"
24#include "xfs_trans.h"
25#include "xfs_sb.h"
26#include "xfs_ag.h"
27#include "xfs_mount.h"
28#include "xfs_bmap_btree.h"
29#include "xfs_alloc_btree.h"
30#include "xfs_ialloc_btree.h"
31#include "xfs_dinode.h"
32#include "xfs_inode.h"
33#include "xfs_inode_item.h"
34#include "xfs_btree.h"
35#include "xfs_btree_trace.h"
36#include "xfs_error.h"
37#include "xfs_trace.h"
38
39
40
41
42kmem_zone_t *xfs_btree_cur_zone;
43
44
45
46
47const __uint32_t xfs_magics[XFS_BTNUM_MAX] = {
48 XFS_ABTB_MAGIC, XFS_ABTC_MAGIC, XFS_BMAP_MAGIC, XFS_IBT_MAGIC
49};
50
51
52STATIC int
53xfs_btree_check_lblock(
54 struct xfs_btree_cur *cur,
55 struct xfs_btree_block *block,
56 int level,
57 struct xfs_buf *bp)
58{
59 int lblock_ok;
60 struct xfs_mount *mp;
61
62 mp = cur->bc_mp;
63 lblock_ok =
64 be32_to_cpu(block->bb_magic) == xfs_magics[cur->bc_btnum] &&
65 be16_to_cpu(block->bb_level) == level &&
66 be16_to_cpu(block->bb_numrecs) <=
67 cur->bc_ops->get_maxrecs(cur, level) &&
68 block->bb_u.l.bb_leftsib &&
69 (be64_to_cpu(block->bb_u.l.bb_leftsib) == NULLDFSBNO ||
70 XFS_FSB_SANITY_CHECK(mp,
71 be64_to_cpu(block->bb_u.l.bb_leftsib))) &&
72 block->bb_u.l.bb_rightsib &&
73 (be64_to_cpu(block->bb_u.l.bb_rightsib) == NULLDFSBNO ||
74 XFS_FSB_SANITY_CHECK(mp,
75 be64_to_cpu(block->bb_u.l.bb_rightsib)));
76 if (unlikely(XFS_TEST_ERROR(!lblock_ok, mp,
77 XFS_ERRTAG_BTREE_CHECK_LBLOCK,
78 XFS_RANDOM_BTREE_CHECK_LBLOCK))) {
79 if (bp)
80 trace_xfs_btree_corrupt(bp, _RET_IP_);
81 XFS_ERROR_REPORT("xfs_btree_check_lblock", XFS_ERRLEVEL_LOW,
82 mp);
83 return XFS_ERROR(EFSCORRUPTED);
84 }
85 return 0;
86}
87
88STATIC int
89xfs_btree_check_sblock(
90 struct xfs_btree_cur *cur,
91 struct xfs_btree_block *block,
92 int level,
93 struct xfs_buf *bp)
94{
95 struct xfs_buf *agbp;
96 struct xfs_agf *agf;
97 xfs_agblock_t agflen;
98 int sblock_ok;
99
100 agbp = cur->bc_private.a.agbp;
101 agf = XFS_BUF_TO_AGF(agbp);
102 agflen = be32_to_cpu(agf->agf_length);
103 sblock_ok =
104 be32_to_cpu(block->bb_magic) == xfs_magics[cur->bc_btnum] &&
105 be16_to_cpu(block->bb_level) == level &&
106 be16_to_cpu(block->bb_numrecs) <=
107 cur->bc_ops->get_maxrecs(cur, level) &&
108 (be32_to_cpu(block->bb_u.s.bb_leftsib) == NULLAGBLOCK ||
109 be32_to_cpu(block->bb_u.s.bb_leftsib) < agflen) &&
110 block->bb_u.s.bb_leftsib &&
111 (be32_to_cpu(block->bb_u.s.bb_rightsib) == NULLAGBLOCK ||
112 be32_to_cpu(block->bb_u.s.bb_rightsib) < agflen) &&
113 block->bb_u.s.bb_rightsib;
114 if (unlikely(XFS_TEST_ERROR(!sblock_ok, cur->bc_mp,
115 XFS_ERRTAG_BTREE_CHECK_SBLOCK,
116 XFS_RANDOM_BTREE_CHECK_SBLOCK))) {
117 if (bp)
118 trace_xfs_btree_corrupt(bp, _RET_IP_);
119 XFS_CORRUPTION_ERROR("xfs_btree_check_sblock",
120 XFS_ERRLEVEL_LOW, cur->bc_mp, block);
121 return XFS_ERROR(EFSCORRUPTED);
122 }
123 return 0;
124}
125
126
127
128
129int
130xfs_btree_check_block(
131 struct xfs_btree_cur *cur,
132 struct xfs_btree_block *block,
133 int level,
134 struct xfs_buf *bp)
135{
136 if (cur->bc_flags & XFS_BTREE_LONG_PTRS)
137 return xfs_btree_check_lblock(cur, block, level, bp);
138 else
139 return xfs_btree_check_sblock(cur, block, level, bp);
140}
141
142
143
144
145int
146xfs_btree_check_lptr(
147 struct xfs_btree_cur *cur,
148 xfs_dfsbno_t bno,
149 int level)
150{
151 XFS_WANT_CORRUPTED_RETURN(
152 level > 0 &&
153 bno != NULLDFSBNO &&
154 XFS_FSB_SANITY_CHECK(cur->bc_mp, bno));
155 return 0;
156}
157
158#ifdef DEBUG
159
160
161
162STATIC int
163xfs_btree_check_sptr(
164 struct xfs_btree_cur *cur,
165 xfs_agblock_t bno,
166 int level)
167{
168 xfs_agblock_t agblocks = cur->bc_mp->m_sb.sb_agblocks;
169
170 XFS_WANT_CORRUPTED_RETURN(
171 level > 0 &&
172 bno != NULLAGBLOCK &&
173 bno != 0 &&
174 bno < agblocks);
175 return 0;
176}
177
178
179
180
181STATIC int
182xfs_btree_check_ptr(
183 struct xfs_btree_cur *cur,
184 union xfs_btree_ptr *ptr,
185 int index,
186 int level)
187{
188 if (cur->bc_flags & XFS_BTREE_LONG_PTRS) {
189 return xfs_btree_check_lptr(cur,
190 be64_to_cpu((&ptr->l)[index]), level);
191 } else {
192 return xfs_btree_check_sptr(cur,
193 be32_to_cpu((&ptr->s)[index]), level);
194 }
195}
196#endif
197
198
199
200
201void
202xfs_btree_del_cursor(
203 xfs_btree_cur_t *cur,
204 int error)
205{
206 int i;
207
208
209
210
211
212
213
214
215
216
217
218 for (i = 0; i < cur->bc_nlevels; i++) {
219 if (cur->bc_bufs[i])
220 xfs_trans_brelse(cur->bc_tp, cur->bc_bufs[i]);
221 else if (!error)
222 break;
223 }
224
225
226
227
228 ASSERT(cur->bc_btnum != XFS_BTNUM_BMAP ||
229 cur->bc_private.b.allocated == 0);
230
231
232
233 kmem_zone_free(xfs_btree_cur_zone, cur);
234}
235
236
237
238
239
240int
241xfs_btree_dup_cursor(
242 xfs_btree_cur_t *cur,
243 xfs_btree_cur_t **ncur)
244{
245 xfs_buf_t *bp;
246 int error;
247 int i;
248 xfs_mount_t *mp;
249 xfs_btree_cur_t *new;
250 xfs_trans_t *tp;
251
252 tp = cur->bc_tp;
253 mp = cur->bc_mp;
254
255
256
257
258 new = cur->bc_ops->dup_cursor(cur);
259
260
261
262
263 new->bc_rec = cur->bc_rec;
264
265
266
267
268 for (i = 0; i < new->bc_nlevels; i++) {
269 new->bc_ptrs[i] = cur->bc_ptrs[i];
270 new->bc_ra[i] = cur->bc_ra[i];
271 if ((bp = cur->bc_bufs[i])) {
272 if ((error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
273 XFS_BUF_ADDR(bp), mp->m_bsize, 0, &bp))) {
274 xfs_btree_del_cursor(new, error);
275 *ncur = NULL;
276 return error;
277 }
278 new->bc_bufs[i] = bp;
279 ASSERT(bp);
280 ASSERT(!XFS_BUF_GETERROR(bp));
281 } else
282 new->bc_bufs[i] = NULL;
283 }
284 *ncur = new;
285 return 0;
286}
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321static inline size_t xfs_btree_block_len(struct xfs_btree_cur *cur)
322{
323 return (cur->bc_flags & XFS_BTREE_LONG_PTRS) ?
324 XFS_BTREE_LBLOCK_LEN :
325 XFS_BTREE_SBLOCK_LEN;
326}
327
328
329
330
331static inline size_t xfs_btree_ptr_len(struct xfs_btree_cur *cur)
332{
333 return (cur->bc_flags & XFS_BTREE_LONG_PTRS) ?
334 sizeof(__be64) : sizeof(__be32);
335}
336
337
338
339
340STATIC size_t
341xfs_btree_rec_offset(
342 struct xfs_btree_cur *cur,
343 int n)
344{
345 return xfs_btree_block_len(cur) +
346 (n - 1) * cur->bc_ops->rec_len;
347}
348
349
350
351
352STATIC size_t
353xfs_btree_key_offset(
354 struct xfs_btree_cur *cur,
355 int n)
356{
357 return xfs_btree_block_len(cur) +
358 (n - 1) * cur->bc_ops->key_len;
359}
360
361
362
363
364STATIC size_t
365xfs_btree_ptr_offset(
366 struct xfs_btree_cur *cur,
367 int n,
368 int level)
369{
370 return xfs_btree_block_len(cur) +
371 cur->bc_ops->get_maxrecs(cur, level) * cur->bc_ops->key_len +
372 (n - 1) * xfs_btree_ptr_len(cur);
373}
374
375
376
377
378STATIC union xfs_btree_rec *
379xfs_btree_rec_addr(
380 struct xfs_btree_cur *cur,
381 int n,
382 struct xfs_btree_block *block)
383{
384 return (union xfs_btree_rec *)
385 ((char *)block + xfs_btree_rec_offset(cur, n));
386}
387
388
389
390
391STATIC union xfs_btree_key *
392xfs_btree_key_addr(
393 struct xfs_btree_cur *cur,
394 int n,
395 struct xfs_btree_block *block)
396{
397 return (union xfs_btree_key *)
398 ((char *)block + xfs_btree_key_offset(cur, n));
399}
400
401
402
403
404STATIC union xfs_btree_ptr *
405xfs_btree_ptr_addr(
406 struct xfs_btree_cur *cur,
407 int n,
408 struct xfs_btree_block *block)
409{
410 int level = xfs_btree_get_level(block);
411
412 ASSERT(block->bb_level != 0);
413
414 return (union xfs_btree_ptr *)
415 ((char *)block + xfs_btree_ptr_offset(cur, n, level));
416}
417
418
419
420
421
422
423
424STATIC struct xfs_btree_block *
425xfs_btree_get_iroot(
426 struct xfs_btree_cur *cur)
427{
428 struct xfs_ifork *ifp;
429
430 ifp = XFS_IFORK_PTR(cur->bc_private.b.ip, cur->bc_private.b.whichfork);
431 return (struct xfs_btree_block *)ifp->if_broot;
432}
433
434
435
436
437
438STATIC struct xfs_btree_block *
439xfs_btree_get_block(
440 struct xfs_btree_cur *cur,
441 int level,
442 struct xfs_buf **bpp)
443{
444 if ((cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) &&
445 (level == cur->bc_nlevels - 1)) {
446 *bpp = NULL;
447 return xfs_btree_get_iroot(cur);
448 }
449
450 *bpp = cur->bc_bufs[level];
451 return XFS_BUF_TO_BLOCK(*bpp);
452}
453
454
455
456
457
458xfs_buf_t *
459xfs_btree_get_bufl(
460 xfs_mount_t *mp,
461 xfs_trans_t *tp,
462 xfs_fsblock_t fsbno,
463 uint lock)
464{
465 xfs_buf_t *bp;
466 xfs_daddr_t d;
467
468 ASSERT(fsbno != NULLFSBLOCK);
469 d = XFS_FSB_TO_DADDR(mp, fsbno);
470 bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, d, mp->m_bsize, lock);
471 ASSERT(bp);
472 ASSERT(!XFS_BUF_GETERROR(bp));
473 return bp;
474}
475
476
477
478
479
480xfs_buf_t *
481xfs_btree_get_bufs(
482 xfs_mount_t *mp,
483 xfs_trans_t *tp,
484 xfs_agnumber_t agno,
485 xfs_agblock_t agbno,
486 uint lock)
487{
488 xfs_buf_t *bp;
489 xfs_daddr_t d;
490
491 ASSERT(agno != NULLAGNUMBER);
492 ASSERT(agbno != NULLAGBLOCK);
493 d = XFS_AGB_TO_DADDR(mp, agno, agbno);
494 bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, d, mp->m_bsize, lock);
495 ASSERT(bp);
496 ASSERT(!XFS_BUF_GETERROR(bp));
497 return bp;
498}
499
500
501
502
503int
504xfs_btree_islastblock(
505 xfs_btree_cur_t *cur,
506 int level)
507{
508 struct xfs_btree_block *block;
509 xfs_buf_t *bp;
510
511 block = xfs_btree_get_block(cur, level, &bp);
512 xfs_btree_check_block(cur, block, level, bp);
513 if (cur->bc_flags & XFS_BTREE_LONG_PTRS)
514 return be64_to_cpu(block->bb_u.l.bb_rightsib) == NULLDFSBNO;
515 else
516 return be32_to_cpu(block->bb_u.s.bb_rightsib) == NULLAGBLOCK;
517}
518
519
520
521
522
523STATIC int
524xfs_btree_firstrec(
525 xfs_btree_cur_t *cur,
526 int level)
527{
528 struct xfs_btree_block *block;
529 xfs_buf_t *bp;
530
531
532
533
534 block = xfs_btree_get_block(cur, level, &bp);
535 xfs_btree_check_block(cur, block, level, bp);
536
537
538
539 if (!block->bb_numrecs)
540 return 0;
541
542
543
544 cur->bc_ptrs[level] = 1;
545 return 1;
546}
547
548
549
550
551
552STATIC int
553xfs_btree_lastrec(
554 xfs_btree_cur_t *cur,
555 int level)
556{
557 struct xfs_btree_block *block;
558 xfs_buf_t *bp;
559
560
561
562
563 block = xfs_btree_get_block(cur, level, &bp);
564 xfs_btree_check_block(cur, block, level, bp);
565
566
567
568 if (!block->bb_numrecs)
569 return 0;
570
571
572
573 cur->bc_ptrs[level] = be16_to_cpu(block->bb_numrecs);
574 return 1;
575}
576
577
578
579
580
581void
582xfs_btree_offsets(
583 __int64_t fields,
584 const short *offsets,
585 int nbits,
586 int *first,
587 int *last)
588{
589 int i;
590 __int64_t imask;
591
592 ASSERT(fields != 0);
593
594
595
596 for (i = 0, imask = 1LL; ; i++, imask <<= 1) {
597 if (imask & fields) {
598 *first = offsets[i];
599 break;
600 }
601 }
602
603
604
605 for (i = nbits - 1, imask = 1LL << i; ; i--, imask >>= 1) {
606 if (imask & fields) {
607 *last = offsets[i + 1] - 1;
608 break;
609 }
610 }
611}
612
613
614
615
616
617int
618xfs_btree_read_bufl(
619 xfs_mount_t *mp,
620 xfs_trans_t *tp,
621 xfs_fsblock_t fsbno,
622 uint lock,
623 xfs_buf_t **bpp,
624 int refval)
625{
626 xfs_buf_t *bp;
627 xfs_daddr_t d;
628 int error;
629
630 ASSERT(fsbno != NULLFSBLOCK);
631 d = XFS_FSB_TO_DADDR(mp, fsbno);
632 if ((error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, d,
633 mp->m_bsize, lock, &bp))) {
634 return error;
635 }
636 ASSERT(!bp || !XFS_BUF_GETERROR(bp));
637 if (bp)
638 XFS_BUF_SET_VTYPE_REF(bp, B_FS_MAP, refval);
639 *bpp = bp;
640 return 0;
641}
642
643
644
645
646
647
648void
649xfs_btree_reada_bufl(
650 xfs_mount_t *mp,
651 xfs_fsblock_t fsbno,
652 xfs_extlen_t count)
653{
654 xfs_daddr_t d;
655
656 ASSERT(fsbno != NULLFSBLOCK);
657 d = XFS_FSB_TO_DADDR(mp, fsbno);
658 xfs_buf_readahead(mp->m_ddev_targp, d, mp->m_bsize * count);
659}
660
661
662
663
664
665
666void
667xfs_btree_reada_bufs(
668 xfs_mount_t *mp,
669 xfs_agnumber_t agno,
670 xfs_agblock_t agbno,
671 xfs_extlen_t count)
672{
673 xfs_daddr_t d;
674
675 ASSERT(agno != NULLAGNUMBER);
676 ASSERT(agbno != NULLAGBLOCK);
677 d = XFS_AGB_TO_DADDR(mp, agno, agbno);
678 xfs_buf_readahead(mp->m_ddev_targp, d, mp->m_bsize * count);
679}
680
681STATIC int
682xfs_btree_readahead_lblock(
683 struct xfs_btree_cur *cur,
684 int lr,
685 struct xfs_btree_block *block)
686{
687 int rval = 0;
688 xfs_dfsbno_t left = be64_to_cpu(block->bb_u.l.bb_leftsib);
689 xfs_dfsbno_t right = be64_to_cpu(block->bb_u.l.bb_rightsib);
690
691 if ((lr & XFS_BTCUR_LEFTRA) && left != NULLDFSBNO) {
692 xfs_btree_reada_bufl(cur->bc_mp, left, 1);
693 rval++;
694 }
695
696 if ((lr & XFS_BTCUR_RIGHTRA) && right != NULLDFSBNO) {
697 xfs_btree_reada_bufl(cur->bc_mp, right, 1);
698 rval++;
699 }
700
701 return rval;
702}
703
704STATIC int
705xfs_btree_readahead_sblock(
706 struct xfs_btree_cur *cur,
707 int lr,
708 struct xfs_btree_block *block)
709{
710 int rval = 0;
711 xfs_agblock_t left = be32_to_cpu(block->bb_u.s.bb_leftsib);
712 xfs_agblock_t right = be32_to_cpu(block->bb_u.s.bb_rightsib);
713
714
715 if ((lr & XFS_BTCUR_LEFTRA) && left != NULLAGBLOCK) {
716 xfs_btree_reada_bufs(cur->bc_mp, cur->bc_private.a.agno,
717 left, 1);
718 rval++;
719 }
720
721 if ((lr & XFS_BTCUR_RIGHTRA) && right != NULLAGBLOCK) {
722 xfs_btree_reada_bufs(cur->bc_mp, cur->bc_private.a.agno,
723 right, 1);
724 rval++;
725 }
726
727 return rval;
728}
729
730
731
732
733
734STATIC int
735xfs_btree_readahead(
736 struct xfs_btree_cur *cur,
737 int lev,
738 int lr)
739{
740 struct xfs_btree_block *block;
741
742
743
744
745
746 if ((cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) &&
747 (lev == cur->bc_nlevels - 1))
748 return 0;
749
750 if ((cur->bc_ra[lev] | lr) == cur->bc_ra[lev])
751 return 0;
752
753 cur->bc_ra[lev] |= lr;
754 block = XFS_BUF_TO_BLOCK(cur->bc_bufs[lev]);
755
756 if (cur->bc_flags & XFS_BTREE_LONG_PTRS)
757 return xfs_btree_readahead_lblock(cur, lr, block);
758 return xfs_btree_readahead_sblock(cur, lr, block);
759}
760
761
762
763
764
765STATIC void
766xfs_btree_setbuf(
767 xfs_btree_cur_t *cur,
768 int lev,
769 xfs_buf_t *bp)
770{
771 struct xfs_btree_block *b;
772
773 if (cur->bc_bufs[lev])
774 xfs_trans_brelse(cur->bc_tp, cur->bc_bufs[lev]);
775 cur->bc_bufs[lev] = bp;
776 cur->bc_ra[lev] = 0;
777
778 b = XFS_BUF_TO_BLOCK(bp);
779 if (cur->bc_flags & XFS_BTREE_LONG_PTRS) {
780 if (be64_to_cpu(b->bb_u.l.bb_leftsib) == NULLDFSBNO)
781 cur->bc_ra[lev] |= XFS_BTCUR_LEFTRA;
782 if (be64_to_cpu(b->bb_u.l.bb_rightsib) == NULLDFSBNO)
783 cur->bc_ra[lev] |= XFS_BTCUR_RIGHTRA;
784 } else {
785 if (be32_to_cpu(b->bb_u.s.bb_leftsib) == NULLAGBLOCK)
786 cur->bc_ra[lev] |= XFS_BTCUR_LEFTRA;
787 if (be32_to_cpu(b->bb_u.s.bb_rightsib) == NULLAGBLOCK)
788 cur->bc_ra[lev] |= XFS_BTCUR_RIGHTRA;
789 }
790}
791
792STATIC int
793xfs_btree_ptr_is_null(
794 struct xfs_btree_cur *cur,
795 union xfs_btree_ptr *ptr)
796{
797 if (cur->bc_flags & XFS_BTREE_LONG_PTRS)
798 return be64_to_cpu(ptr->l) == NULLDFSBNO;
799 else
800 return be32_to_cpu(ptr->s) == NULLAGBLOCK;
801}
802
803STATIC void
804xfs_btree_set_ptr_null(
805 struct xfs_btree_cur *cur,
806 union xfs_btree_ptr *ptr)
807{
808 if (cur->bc_flags & XFS_BTREE_LONG_PTRS)
809 ptr->l = cpu_to_be64(NULLDFSBNO);
810 else
811 ptr->s = cpu_to_be32(NULLAGBLOCK);
812}
813
814
815
816
817STATIC void
818xfs_btree_get_sibling(
819 struct xfs_btree_cur *cur,
820 struct xfs_btree_block *block,
821 union xfs_btree_ptr *ptr,
822 int lr)
823{
824 ASSERT(lr == XFS_BB_LEFTSIB || lr == XFS_BB_RIGHTSIB);
825
826 if (cur->bc_flags & XFS_BTREE_LONG_PTRS) {
827 if (lr == XFS_BB_RIGHTSIB)
828 ptr->l = block->bb_u.l.bb_rightsib;
829 else
830 ptr->l = block->bb_u.l.bb_leftsib;
831 } else {
832 if (lr == XFS_BB_RIGHTSIB)
833 ptr->s = block->bb_u.s.bb_rightsib;
834 else
835 ptr->s = block->bb_u.s.bb_leftsib;
836 }
837}
838
839STATIC void
840xfs_btree_set_sibling(
841 struct xfs_btree_cur *cur,
842 struct xfs_btree_block *block,
843 union xfs_btree_ptr *ptr,
844 int lr)
845{
846 ASSERT(lr == XFS_BB_LEFTSIB || lr == XFS_BB_RIGHTSIB);
847
848 if (cur->bc_flags & XFS_BTREE_LONG_PTRS) {
849 if (lr == XFS_BB_RIGHTSIB)
850 block->bb_u.l.bb_rightsib = ptr->l;
851 else
852 block->bb_u.l.bb_leftsib = ptr->l;
853 } else {
854 if (lr == XFS_BB_RIGHTSIB)
855 block->bb_u.s.bb_rightsib = ptr->s;
856 else
857 block->bb_u.s.bb_leftsib = ptr->s;
858 }
859}
860
861STATIC void
862xfs_btree_init_block(
863 struct xfs_btree_cur *cur,
864 int level,
865 int numrecs,
866 struct xfs_btree_block *new)
867{
868 new->bb_magic = cpu_to_be32(xfs_magics[cur->bc_btnum]);
869 new->bb_level = cpu_to_be16(level);
870 new->bb_numrecs = cpu_to_be16(numrecs);
871
872 if (cur->bc_flags & XFS_BTREE_LONG_PTRS) {
873 new->bb_u.l.bb_leftsib = cpu_to_be64(NULLDFSBNO);
874 new->bb_u.l.bb_rightsib = cpu_to_be64(NULLDFSBNO);
875 } else {
876 new->bb_u.s.bb_leftsib = cpu_to_be32(NULLAGBLOCK);
877 new->bb_u.s.bb_rightsib = cpu_to_be32(NULLAGBLOCK);
878 }
879}
880
881
882
883
884
885
886STATIC int
887xfs_btree_is_lastrec(
888 struct xfs_btree_cur *cur,
889 struct xfs_btree_block *block,
890 int level)
891{
892 union xfs_btree_ptr ptr;
893
894 if (level > 0)
895 return 0;
896 if (!(cur->bc_flags & XFS_BTREE_LASTREC_UPDATE))
897 return 0;
898
899 xfs_btree_get_sibling(cur, block, &ptr, XFS_BB_RIGHTSIB);
900 if (!xfs_btree_ptr_is_null(cur, &ptr))
901 return 0;
902 return 1;
903}
904
905STATIC void
906xfs_btree_buf_to_ptr(
907 struct xfs_btree_cur *cur,
908 struct xfs_buf *bp,
909 union xfs_btree_ptr *ptr)
910{
911 if (cur->bc_flags & XFS_BTREE_LONG_PTRS)
912 ptr->l = cpu_to_be64(XFS_DADDR_TO_FSB(cur->bc_mp,
913 XFS_BUF_ADDR(bp)));
914 else {
915 ptr->s = cpu_to_be32(xfs_daddr_to_agbno(cur->bc_mp,
916 XFS_BUF_ADDR(bp)));
917 }
918}
919
920STATIC xfs_daddr_t
921xfs_btree_ptr_to_daddr(
922 struct xfs_btree_cur *cur,
923 union xfs_btree_ptr *ptr)
924{
925 if (cur->bc_flags & XFS_BTREE_LONG_PTRS) {
926 ASSERT(be64_to_cpu(ptr->l) != NULLDFSBNO);
927
928 return XFS_FSB_TO_DADDR(cur->bc_mp, be64_to_cpu(ptr->l));
929 } else {
930 ASSERT(cur->bc_private.a.agno != NULLAGNUMBER);
931 ASSERT(be32_to_cpu(ptr->s) != NULLAGBLOCK);
932
933 return XFS_AGB_TO_DADDR(cur->bc_mp, cur->bc_private.a.agno,
934 be32_to_cpu(ptr->s));
935 }
936}
937
938STATIC void
939xfs_btree_set_refs(
940 struct xfs_btree_cur *cur,
941 struct xfs_buf *bp)
942{
943 switch (cur->bc_btnum) {
944 case XFS_BTNUM_BNO:
945 case XFS_BTNUM_CNT:
946 XFS_BUF_SET_VTYPE_REF(bp, B_FS_MAP, XFS_ALLOC_BTREE_REF);
947 break;
948 case XFS_BTNUM_INO:
949 XFS_BUF_SET_VTYPE_REF(bp, B_FS_INOMAP, XFS_INO_BTREE_REF);
950 break;
951 case XFS_BTNUM_BMAP:
952 XFS_BUF_SET_VTYPE_REF(bp, B_FS_MAP, XFS_BMAP_BTREE_REF);
953 break;
954 default:
955 ASSERT(0);
956 }
957}
958
959STATIC int
960xfs_btree_get_buf_block(
961 struct xfs_btree_cur *cur,
962 union xfs_btree_ptr *ptr,
963 int flags,
964 struct xfs_btree_block **block,
965 struct xfs_buf **bpp)
966{
967 struct xfs_mount *mp = cur->bc_mp;
968 xfs_daddr_t d;
969
970
971 ASSERT(!(flags & XBF_TRYLOCK));
972
973 d = xfs_btree_ptr_to_daddr(cur, ptr);
974 *bpp = xfs_trans_get_buf(cur->bc_tp, mp->m_ddev_targp, d,
975 mp->m_bsize, flags);
976
977 ASSERT(*bpp);
978 ASSERT(!XFS_BUF_GETERROR(*bpp));
979
980 *block = XFS_BUF_TO_BLOCK(*bpp);
981 return 0;
982}
983
984
985
986
987
988STATIC int
989xfs_btree_read_buf_block(
990 struct xfs_btree_cur *cur,
991 union xfs_btree_ptr *ptr,
992 int level,
993 int flags,
994 struct xfs_btree_block **block,
995 struct xfs_buf **bpp)
996{
997 struct xfs_mount *mp = cur->bc_mp;
998 xfs_daddr_t d;
999 int error;
1000
1001
1002 ASSERT(!(flags & XBF_TRYLOCK));
1003
1004 d = xfs_btree_ptr_to_daddr(cur, ptr);
1005 error = xfs_trans_read_buf(mp, cur->bc_tp, mp->m_ddev_targp, d,
1006 mp->m_bsize, flags, bpp);
1007 if (error)
1008 return error;
1009
1010 ASSERT(*bpp != NULL);
1011 ASSERT(!XFS_BUF_GETERROR(*bpp));
1012
1013 xfs_btree_set_refs(cur, *bpp);
1014 *block = XFS_BUF_TO_BLOCK(*bpp);
1015
1016 error = xfs_btree_check_block(cur, *block, level, *bpp);
1017 if (error)
1018 xfs_trans_brelse(cur->bc_tp, *bpp);
1019 return error;
1020}
1021
1022
1023
1024
1025STATIC void
1026xfs_btree_copy_keys(
1027 struct xfs_btree_cur *cur,
1028 union xfs_btree_key *dst_key,
1029 union xfs_btree_key *src_key,
1030 int numkeys)
1031{
1032 ASSERT(numkeys >= 0);
1033 memcpy(dst_key, src_key, numkeys * cur->bc_ops->key_len);
1034}
1035
1036
1037
1038
1039STATIC void
1040xfs_btree_copy_recs(
1041 struct xfs_btree_cur *cur,
1042 union xfs_btree_rec *dst_rec,
1043 union xfs_btree_rec *src_rec,
1044 int numrecs)
1045{
1046 ASSERT(numrecs >= 0);
1047 memcpy(dst_rec, src_rec, numrecs * cur->bc_ops->rec_len);
1048}
1049
1050
1051
1052
1053STATIC void
1054xfs_btree_copy_ptrs(
1055 struct xfs_btree_cur *cur,
1056 union xfs_btree_ptr *dst_ptr,
1057 union xfs_btree_ptr *src_ptr,
1058 int numptrs)
1059{
1060 ASSERT(numptrs >= 0);
1061 memcpy(dst_ptr, src_ptr, numptrs * xfs_btree_ptr_len(cur));
1062}
1063
1064
1065
1066
1067STATIC void
1068xfs_btree_shift_keys(
1069 struct xfs_btree_cur *cur,
1070 union xfs_btree_key *key,
1071 int dir,
1072 int numkeys)
1073{
1074 char *dst_key;
1075
1076 ASSERT(numkeys >= 0);
1077 ASSERT(dir == 1 || dir == -1);
1078
1079 dst_key = (char *)key + (dir * cur->bc_ops->key_len);
1080 memmove(dst_key, key, numkeys * cur->bc_ops->key_len);
1081}
1082
1083
1084
1085
1086STATIC void
1087xfs_btree_shift_recs(
1088 struct xfs_btree_cur *cur,
1089 union xfs_btree_rec *rec,
1090 int dir,
1091 int numrecs)
1092{
1093 char *dst_rec;
1094
1095 ASSERT(numrecs >= 0);
1096 ASSERT(dir == 1 || dir == -1);
1097
1098 dst_rec = (char *)rec + (dir * cur->bc_ops->rec_len);
1099 memmove(dst_rec, rec, numrecs * cur->bc_ops->rec_len);
1100}
1101
1102
1103
1104
1105STATIC void
1106xfs_btree_shift_ptrs(
1107 struct xfs_btree_cur *cur,
1108 union xfs_btree_ptr *ptr,
1109 int dir,
1110 int numptrs)
1111{
1112 char *dst_ptr;
1113
1114 ASSERT(numptrs >= 0);
1115 ASSERT(dir == 1 || dir == -1);
1116
1117 dst_ptr = (char *)ptr + (dir * xfs_btree_ptr_len(cur));
1118 memmove(dst_ptr, ptr, numptrs * xfs_btree_ptr_len(cur));
1119}
1120
1121
1122
1123
1124STATIC void
1125xfs_btree_log_keys(
1126 struct xfs_btree_cur *cur,
1127 struct xfs_buf *bp,
1128 int first,
1129 int last)
1130{
1131 XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY);
1132 XFS_BTREE_TRACE_ARGBII(cur, bp, first, last);
1133
1134 if (bp) {
1135 xfs_trans_log_buf(cur->bc_tp, bp,
1136 xfs_btree_key_offset(cur, first),
1137 xfs_btree_key_offset(cur, last + 1) - 1);
1138 } else {
1139 xfs_trans_log_inode(cur->bc_tp, cur->bc_private.b.ip,
1140 xfs_ilog_fbroot(cur->bc_private.b.whichfork));
1141 }
1142
1143 XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
1144}
1145
1146
1147
1148
1149void
1150xfs_btree_log_recs(
1151 struct xfs_btree_cur *cur,
1152 struct xfs_buf *bp,
1153 int first,
1154 int last)
1155{
1156 XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY);
1157 XFS_BTREE_TRACE_ARGBII(cur, bp, first, last);
1158
1159 xfs_trans_log_buf(cur->bc_tp, bp,
1160 xfs_btree_rec_offset(cur, first),
1161 xfs_btree_rec_offset(cur, last + 1) - 1);
1162
1163 XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
1164}
1165
1166
1167
1168
1169STATIC void
1170xfs_btree_log_ptrs(
1171 struct xfs_btree_cur *cur,
1172 struct xfs_buf *bp,
1173 int first,
1174 int last)
1175{
1176 XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY);
1177 XFS_BTREE_TRACE_ARGBII(cur, bp, first, last);
1178
1179 if (bp) {
1180 struct xfs_btree_block *block = XFS_BUF_TO_BLOCK(bp);
1181 int level = xfs_btree_get_level(block);
1182
1183 xfs_trans_log_buf(cur->bc_tp, bp,
1184 xfs_btree_ptr_offset(cur, first, level),
1185 xfs_btree_ptr_offset(cur, last + 1, level) - 1);
1186 } else {
1187 xfs_trans_log_inode(cur->bc_tp, cur->bc_private.b.ip,
1188 xfs_ilog_fbroot(cur->bc_private.b.whichfork));
1189 }
1190
1191 XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
1192}
1193
1194
1195
1196
1197void
1198xfs_btree_log_block(
1199 struct xfs_btree_cur *cur,
1200 struct xfs_buf *bp,
1201 int fields)
1202{
1203 int first;
1204 int last;
1205 static const short soffsets[] = {
1206 offsetof(struct xfs_btree_block, bb_magic),
1207 offsetof(struct xfs_btree_block, bb_level),
1208 offsetof(struct xfs_btree_block, bb_numrecs),
1209 offsetof(struct xfs_btree_block, bb_u.s.bb_leftsib),
1210 offsetof(struct xfs_btree_block, bb_u.s.bb_rightsib),
1211 XFS_BTREE_SBLOCK_LEN
1212 };
1213 static const short loffsets[] = {
1214 offsetof(struct xfs_btree_block, bb_magic),
1215 offsetof(struct xfs_btree_block, bb_level),
1216 offsetof(struct xfs_btree_block, bb_numrecs),
1217 offsetof(struct xfs_btree_block, bb_u.l.bb_leftsib),
1218 offsetof(struct xfs_btree_block, bb_u.l.bb_rightsib),
1219 XFS_BTREE_LBLOCK_LEN
1220 };
1221
1222 XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY);
1223 XFS_BTREE_TRACE_ARGBI(cur, bp, fields);
1224
1225 if (bp) {
1226 xfs_btree_offsets(fields,
1227 (cur->bc_flags & XFS_BTREE_LONG_PTRS) ?
1228 loffsets : soffsets,
1229 XFS_BB_NUM_BITS, &first, &last);
1230 xfs_trans_log_buf(cur->bc_tp, bp, first, last);
1231 } else {
1232 xfs_trans_log_inode(cur->bc_tp, cur->bc_private.b.ip,
1233 xfs_ilog_fbroot(cur->bc_private.b.whichfork));
1234 }
1235
1236 XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
1237}
1238
1239
1240
1241
1242
1243int
1244xfs_btree_increment(
1245 struct xfs_btree_cur *cur,
1246 int level,
1247 int *stat)
1248{
1249 struct xfs_btree_block *block;
1250 union xfs_btree_ptr ptr;
1251 struct xfs_buf *bp;
1252 int error;
1253 int lev;
1254
1255 XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY);
1256 XFS_BTREE_TRACE_ARGI(cur, level);
1257
1258 ASSERT(level < cur->bc_nlevels);
1259
1260
1261 xfs_btree_readahead(cur, level, XFS_BTCUR_RIGHTRA);
1262
1263
1264 block = xfs_btree_get_block(cur, level, &bp);
1265
1266#ifdef DEBUG
1267 error = xfs_btree_check_block(cur, block, level, bp);
1268 if (error)
1269 goto error0;
1270#endif
1271
1272
1273 if (++cur->bc_ptrs[level] <= xfs_btree_get_numrecs(block))
1274 goto out1;
1275
1276
1277 xfs_btree_get_sibling(cur, block, &ptr, XFS_BB_RIGHTSIB);
1278 if (xfs_btree_ptr_is_null(cur, &ptr))
1279 goto out0;
1280
1281 XFS_BTREE_STATS_INC(cur, increment);
1282
1283
1284
1285
1286
1287 for (lev = level + 1; lev < cur->bc_nlevels; lev++) {
1288 block = xfs_btree_get_block(cur, lev, &bp);
1289
1290#ifdef DEBUG
1291 error = xfs_btree_check_block(cur, block, lev, bp);
1292 if (error)
1293 goto error0;
1294#endif
1295
1296 if (++cur->bc_ptrs[lev] <= xfs_btree_get_numrecs(block))
1297 break;
1298
1299
1300 xfs_btree_readahead(cur, lev, XFS_BTCUR_RIGHTRA);
1301 }
1302
1303
1304
1305
1306
1307 if (lev == cur->bc_nlevels) {
1308 if (cur->bc_flags & XFS_BTREE_ROOT_IN_INODE)
1309 goto out0;
1310 ASSERT(0);
1311 error = EFSCORRUPTED;
1312 goto error0;
1313 }
1314 ASSERT(lev < cur->bc_nlevels);
1315
1316
1317
1318
1319
1320 for (block = xfs_btree_get_block(cur, lev, &bp); lev > level; ) {
1321 union xfs_btree_ptr *ptrp;
1322
1323 ptrp = xfs_btree_ptr_addr(cur, cur->bc_ptrs[lev], block);
1324 error = xfs_btree_read_buf_block(cur, ptrp, --lev,
1325 0, &block, &bp);
1326 if (error)
1327 goto error0;
1328
1329 xfs_btree_setbuf(cur, lev, bp);
1330 cur->bc_ptrs[lev] = 1;
1331 }
1332out1:
1333 XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
1334 *stat = 1;
1335 return 0;
1336
1337out0:
1338 XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
1339 *stat = 0;
1340 return 0;
1341
1342error0:
1343 XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR);
1344 return error;
1345}
1346
1347
1348
1349
1350
1351int
1352xfs_btree_decrement(
1353 struct xfs_btree_cur *cur,
1354 int level,
1355 int *stat)
1356{
1357 struct xfs_btree_block *block;
1358 xfs_buf_t *bp;
1359 int error;
1360 int lev;
1361 union xfs_btree_ptr ptr;
1362
1363 XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY);
1364 XFS_BTREE_TRACE_ARGI(cur, level);
1365
1366 ASSERT(level < cur->bc_nlevels);
1367
1368
1369 xfs_btree_readahead(cur, level, XFS_BTCUR_LEFTRA);
1370
1371
1372 if (--cur->bc_ptrs[level] > 0)
1373 goto out1;
1374
1375
1376 block = xfs_btree_get_block(cur, level, &bp);
1377
1378#ifdef DEBUG
1379 error = xfs_btree_check_block(cur, block, level, bp);
1380 if (error)
1381 goto error0;
1382#endif
1383
1384
1385 xfs_btree_get_sibling(cur, block, &ptr, XFS_BB_LEFTSIB);
1386 if (xfs_btree_ptr_is_null(cur, &ptr))
1387 goto out0;
1388
1389 XFS_BTREE_STATS_INC(cur, decrement);
1390
1391
1392
1393
1394
1395 for (lev = level + 1; lev < cur->bc_nlevels; lev++) {
1396 if (--cur->bc_ptrs[lev] > 0)
1397 break;
1398
1399 xfs_btree_readahead(cur, lev, XFS_BTCUR_LEFTRA);
1400 }
1401
1402
1403
1404
1405
1406 if (lev == cur->bc_nlevels) {
1407 if (cur->bc_flags & XFS_BTREE_ROOT_IN_INODE)
1408 goto out0;
1409 ASSERT(0);
1410 error = EFSCORRUPTED;
1411 goto error0;
1412 }
1413 ASSERT(lev < cur->bc_nlevels);
1414
1415
1416
1417
1418
1419 for (block = xfs_btree_get_block(cur, lev, &bp); lev > level; ) {
1420 union xfs_btree_ptr *ptrp;
1421
1422 ptrp = xfs_btree_ptr_addr(cur, cur->bc_ptrs[lev], block);
1423 error = xfs_btree_read_buf_block(cur, ptrp, --lev,
1424 0, &block, &bp);
1425 if (error)
1426 goto error0;
1427 xfs_btree_setbuf(cur, lev, bp);
1428 cur->bc_ptrs[lev] = xfs_btree_get_numrecs(block);
1429 }
1430out1:
1431 XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
1432 *stat = 1;
1433 return 0;
1434
1435out0:
1436 XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
1437 *stat = 0;
1438 return 0;
1439
1440error0:
1441 XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR);
1442 return error;
1443}
1444
1445STATIC int
1446xfs_btree_lookup_get_block(
1447 struct xfs_btree_cur *cur,
1448 int level,
1449 union xfs_btree_ptr *pp,
1450 struct xfs_btree_block **blkp)
1451{
1452 struct xfs_buf *bp;
1453 int error = 0;
1454
1455
1456 if ((cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) &&
1457 (level == cur->bc_nlevels - 1)) {
1458 *blkp = xfs_btree_get_iroot(cur);
1459 return 0;
1460 }
1461
1462
1463
1464
1465
1466
1467
1468 bp = cur->bc_bufs[level];
1469 if (bp && XFS_BUF_ADDR(bp) == xfs_btree_ptr_to_daddr(cur, pp)) {
1470 *blkp = XFS_BUF_TO_BLOCK(bp);
1471 return 0;
1472 }
1473
1474 error = xfs_btree_read_buf_block(cur, pp, level, 0, blkp, &bp);
1475 if (error)
1476 return error;
1477
1478 xfs_btree_setbuf(cur, level, bp);
1479 return 0;
1480}
1481
1482
1483
1484
1485
1486
1487STATIC union xfs_btree_key *
1488xfs_lookup_get_search_key(
1489 struct xfs_btree_cur *cur,
1490 int level,
1491 int keyno,
1492 struct xfs_btree_block *block,
1493 union xfs_btree_key *kp)
1494{
1495 if (level == 0) {
1496 cur->bc_ops->init_key_from_rec(kp,
1497 xfs_btree_rec_addr(cur, keyno, block));
1498 return kp;
1499 }
1500
1501 return xfs_btree_key_addr(cur, keyno, block);
1502}
1503
1504
1505
1506
1507
1508int
1509xfs_btree_lookup(
1510 struct xfs_btree_cur *cur,
1511 xfs_lookup_t dir,
1512 int *stat)
1513{
1514 struct xfs_btree_block *block;
1515 __int64_t diff;
1516 int error;
1517 int keyno;
1518 int level;
1519 union xfs_btree_ptr *pp;
1520 union xfs_btree_ptr ptr;
1521
1522 XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY);
1523 XFS_BTREE_TRACE_ARGI(cur, dir);
1524
1525 XFS_BTREE_STATS_INC(cur, lookup);
1526
1527 block = NULL;
1528 keyno = 0;
1529
1530
1531 cur->bc_ops->init_ptr_from_cur(cur, &ptr);
1532 pp = &ptr;
1533
1534
1535
1536
1537
1538
1539
1540 for (level = cur->bc_nlevels - 1, diff = 1; level >= 0; level--) {
1541
1542 error = xfs_btree_lookup_get_block(cur, level, pp, &block);
1543 if (error)
1544 goto error0;
1545
1546 if (diff == 0) {
1547
1548
1549
1550
1551 keyno = 1;
1552 } else {
1553
1554
1555 int high;
1556 int low;
1557
1558
1559 low = 1;
1560 high = xfs_btree_get_numrecs(block);
1561 if (!high) {
1562
1563 ASSERT(level == 0 && cur->bc_nlevels == 1);
1564
1565 cur->bc_ptrs[0] = dir != XFS_LOOKUP_LE;
1566 XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
1567 *stat = 0;
1568 return 0;
1569 }
1570
1571
1572 while (low <= high) {
1573 union xfs_btree_key key;
1574 union xfs_btree_key *kp;
1575
1576 XFS_BTREE_STATS_INC(cur, compare);
1577
1578
1579 keyno = (low + high) >> 1;
1580
1581
1582 kp = xfs_lookup_get_search_key(cur, level,
1583 keyno, block, &key);
1584
1585
1586
1587
1588
1589
1590
1591 diff = cur->bc_ops->key_diff(cur, kp);
1592 if (diff < 0)
1593 low = keyno + 1;
1594 else if (diff > 0)
1595 high = keyno - 1;
1596 else
1597 break;
1598 }
1599 }
1600
1601
1602
1603
1604
1605 if (level > 0) {
1606
1607
1608
1609
1610 if (diff > 0 && --keyno < 1)
1611 keyno = 1;
1612 pp = xfs_btree_ptr_addr(cur, keyno, block);
1613
1614#ifdef DEBUG
1615 error = xfs_btree_check_ptr(cur, pp, 0, level);
1616 if (error)
1617 goto error0;
1618#endif
1619 cur->bc_ptrs[level] = keyno;
1620 }
1621 }
1622
1623
1624 if (dir != XFS_LOOKUP_LE && diff < 0) {
1625 keyno++;
1626
1627
1628
1629
1630 xfs_btree_get_sibling(cur, block, &ptr, XFS_BB_RIGHTSIB);
1631 if (dir == XFS_LOOKUP_GE &&
1632 keyno > xfs_btree_get_numrecs(block) &&
1633 !xfs_btree_ptr_is_null(cur, &ptr)) {
1634 int i;
1635
1636 cur->bc_ptrs[0] = keyno;
1637 error = xfs_btree_increment(cur, 0, &i);
1638 if (error)
1639 goto error0;
1640 XFS_WANT_CORRUPTED_RETURN(i == 1);
1641 XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
1642 *stat = 1;
1643 return 0;
1644 }
1645 } else if (dir == XFS_LOOKUP_LE && diff > 0)
1646 keyno--;
1647 cur->bc_ptrs[0] = keyno;
1648
1649
1650 if (keyno == 0 || keyno > xfs_btree_get_numrecs(block))
1651 *stat = 0;
1652 else if (dir != XFS_LOOKUP_EQ || diff == 0)
1653 *stat = 1;
1654 else
1655 *stat = 0;
1656 XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
1657 return 0;
1658
1659error0:
1660 XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR);
1661 return error;
1662}
1663
1664
1665
1666
1667STATIC int
1668xfs_btree_updkey(
1669 struct xfs_btree_cur *cur,
1670 union xfs_btree_key *keyp,
1671 int level)
1672{
1673 struct xfs_btree_block *block;
1674 struct xfs_buf *bp;
1675 union xfs_btree_key *kp;
1676 int ptr;
1677
1678 XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY);
1679 XFS_BTREE_TRACE_ARGIK(cur, level, keyp);
1680
1681 ASSERT(!(cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) || level >= 1);
1682
1683
1684
1685
1686
1687
1688
1689 for (ptr = 1; ptr == 1 && level < cur->bc_nlevels; level++) {
1690#ifdef DEBUG
1691 int error;
1692#endif
1693 block = xfs_btree_get_block(cur, level, &bp);
1694#ifdef DEBUG
1695 error = xfs_btree_check_block(cur, block, level, bp);
1696 if (error) {
1697 XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR);
1698 return error;
1699 }
1700#endif
1701 ptr = cur->bc_ptrs[level];
1702 kp = xfs_btree_key_addr(cur, ptr, block);
1703 xfs_btree_copy_keys(cur, kp, keyp, 1);
1704 xfs_btree_log_keys(cur, bp, ptr, ptr);
1705 }
1706
1707 XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
1708 return 0;
1709}
1710
1711
1712
1713
1714
1715
1716int
1717xfs_btree_update(
1718 struct xfs_btree_cur *cur,
1719 union xfs_btree_rec *rec)
1720{
1721 struct xfs_btree_block *block;
1722 struct xfs_buf *bp;
1723 int error;
1724 int ptr;
1725 union xfs_btree_rec *rp;
1726
1727 XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY);
1728 XFS_BTREE_TRACE_ARGR(cur, rec);
1729
1730
1731 block = xfs_btree_get_block(cur, 0, &bp);
1732
1733#ifdef DEBUG
1734 error = xfs_btree_check_block(cur, block, 0, bp);
1735 if (error)
1736 goto error0;
1737#endif
1738
1739 ptr = cur->bc_ptrs[0];
1740 rp = xfs_btree_rec_addr(cur, ptr, block);
1741
1742
1743 xfs_btree_copy_recs(cur, rp, rec, 1);
1744 xfs_btree_log_recs(cur, bp, ptr, ptr);
1745
1746
1747
1748
1749
1750 if (xfs_btree_is_lastrec(cur, block, 0)) {
1751 cur->bc_ops->update_lastrec(cur, block, rec,
1752 ptr, LASTREC_UPDATE);
1753 }
1754
1755
1756 if (ptr == 1) {
1757 union xfs_btree_key key;
1758
1759 cur->bc_ops->init_key_from_rec(&key, rec);
1760 error = xfs_btree_updkey(cur, &key, 1);
1761 if (error)
1762 goto error0;
1763 }
1764
1765 XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
1766 return 0;
1767
1768error0:
1769 XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR);
1770 return error;
1771}
1772
1773
1774
1775
1776
1777STATIC int
1778xfs_btree_lshift(
1779 struct xfs_btree_cur *cur,
1780 int level,
1781 int *stat)
1782{
1783 union xfs_btree_key key;
1784 struct xfs_buf *lbp;
1785 struct xfs_btree_block *left;
1786 int lrecs;
1787 struct xfs_buf *rbp;
1788 struct xfs_btree_block *right;
1789 int rrecs;
1790 union xfs_btree_ptr lptr;
1791 union xfs_btree_key *rkp = NULL;
1792 union xfs_btree_ptr *rpp = NULL;
1793 union xfs_btree_rec *rrp = NULL;
1794 int error;
1795
1796 XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY);
1797 XFS_BTREE_TRACE_ARGI(cur, level);
1798
1799 if ((cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) &&
1800 level == cur->bc_nlevels - 1)
1801 goto out0;
1802
1803
1804 right = xfs_btree_get_block(cur, level, &rbp);
1805
1806#ifdef DEBUG
1807 error = xfs_btree_check_block(cur, right, level, rbp);
1808 if (error)
1809 goto error0;
1810#endif
1811
1812
1813 xfs_btree_get_sibling(cur, right, &lptr, XFS_BB_LEFTSIB);
1814 if (xfs_btree_ptr_is_null(cur, &lptr))
1815 goto out0;
1816
1817
1818
1819
1820
1821 if (cur->bc_ptrs[level] <= 1)
1822 goto out0;
1823
1824
1825 error = xfs_btree_read_buf_block(cur, &lptr, level, 0, &left, &lbp);
1826 if (error)
1827 goto error0;
1828
1829
1830 lrecs = xfs_btree_get_numrecs(left);
1831 if (lrecs == cur->bc_ops->get_maxrecs(cur, level))
1832 goto out0;
1833
1834 rrecs = xfs_btree_get_numrecs(right);
1835
1836
1837
1838
1839
1840
1841 lrecs++;
1842 rrecs--;
1843
1844 XFS_BTREE_STATS_INC(cur, lshift);
1845 XFS_BTREE_STATS_ADD(cur, moves, 1);
1846
1847
1848
1849
1850
1851 if (level > 0) {
1852
1853 union xfs_btree_key *lkp;
1854 union xfs_btree_ptr *lpp;
1855
1856 lkp = xfs_btree_key_addr(cur, lrecs, left);
1857 rkp = xfs_btree_key_addr(cur, 1, right);
1858
1859 lpp = xfs_btree_ptr_addr(cur, lrecs, left);
1860 rpp = xfs_btree_ptr_addr(cur, 1, right);
1861#ifdef DEBUG
1862 error = xfs_btree_check_ptr(cur, rpp, 0, level);
1863 if (error)
1864 goto error0;
1865#endif
1866 xfs_btree_copy_keys(cur, lkp, rkp, 1);
1867 xfs_btree_copy_ptrs(cur, lpp, rpp, 1);
1868
1869 xfs_btree_log_keys(cur, lbp, lrecs, lrecs);
1870 xfs_btree_log_ptrs(cur, lbp, lrecs, lrecs);
1871
1872 ASSERT(cur->bc_ops->keys_inorder(cur,
1873 xfs_btree_key_addr(cur, lrecs - 1, left), lkp));
1874 } else {
1875
1876 union xfs_btree_rec *lrp;
1877
1878 lrp = xfs_btree_rec_addr(cur, lrecs, left);
1879 rrp = xfs_btree_rec_addr(cur, 1, right);
1880
1881 xfs_btree_copy_recs(cur, lrp, rrp, 1);
1882 xfs_btree_log_recs(cur, lbp, lrecs, lrecs);
1883
1884 ASSERT(cur->bc_ops->recs_inorder(cur,
1885 xfs_btree_rec_addr(cur, lrecs - 1, left), lrp));
1886 }
1887
1888 xfs_btree_set_numrecs(left, lrecs);
1889 xfs_btree_log_block(cur, lbp, XFS_BB_NUMRECS);
1890
1891 xfs_btree_set_numrecs(right, rrecs);
1892 xfs_btree_log_block(cur, rbp, XFS_BB_NUMRECS);
1893
1894
1895
1896
1897 XFS_BTREE_STATS_ADD(cur, moves, rrecs - 1);
1898 if (level > 0) {
1899
1900#ifdef DEBUG
1901 int i;
1902
1903 for (i = 0; i < rrecs; i++) {
1904 error = xfs_btree_check_ptr(cur, rpp, i + 1, level);
1905 if (error)
1906 goto error0;
1907 }
1908#endif
1909 xfs_btree_shift_keys(cur,
1910 xfs_btree_key_addr(cur, 2, right),
1911 -1, rrecs);
1912 xfs_btree_shift_ptrs(cur,
1913 xfs_btree_ptr_addr(cur, 2, right),
1914 -1, rrecs);
1915
1916 xfs_btree_log_keys(cur, rbp, 1, rrecs);
1917 xfs_btree_log_ptrs(cur, rbp, 1, rrecs);
1918 } else {
1919
1920 xfs_btree_shift_recs(cur,
1921 xfs_btree_rec_addr(cur, 2, right),
1922 -1, rrecs);
1923 xfs_btree_log_recs(cur, rbp, 1, rrecs);
1924
1925
1926
1927
1928
1929 cur->bc_ops->init_key_from_rec(&key,
1930 xfs_btree_rec_addr(cur, 1, right));
1931 rkp = &key;
1932 }
1933
1934
1935 error = xfs_btree_updkey(cur, rkp, level + 1);
1936 if (error)
1937 goto error0;
1938
1939
1940 cur->bc_ptrs[level]--;
1941
1942 XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
1943 *stat = 1;
1944 return 0;
1945
1946out0:
1947 XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
1948 *stat = 0;
1949 return 0;
1950
1951error0:
1952 XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR);
1953 return error;
1954}
1955
1956
1957
1958
1959
1960STATIC int
1961xfs_btree_rshift(
1962 struct xfs_btree_cur *cur,
1963 int level,
1964 int *stat)
1965{
1966 union xfs_btree_key key;
1967 struct xfs_buf *lbp;
1968 struct xfs_btree_block *left;
1969 struct xfs_buf *rbp;
1970 struct xfs_btree_block *right;
1971 struct xfs_btree_cur *tcur;
1972 union xfs_btree_ptr rptr;
1973 union xfs_btree_key *rkp;
1974 int rrecs;
1975 int lrecs;
1976 int error;
1977 int i;
1978
1979 XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY);
1980 XFS_BTREE_TRACE_ARGI(cur, level);
1981
1982 if ((cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) &&
1983 (level == cur->bc_nlevels - 1))
1984 goto out0;
1985
1986
1987 left = xfs_btree_get_block(cur, level, &lbp);
1988
1989#ifdef DEBUG
1990 error = xfs_btree_check_block(cur, left, level, lbp);
1991 if (error)
1992 goto error0;
1993#endif
1994
1995
1996 xfs_btree_get_sibling(cur, left, &rptr, XFS_BB_RIGHTSIB);
1997 if (xfs_btree_ptr_is_null(cur, &rptr))
1998 goto out0;
1999
2000
2001
2002
2003
2004 lrecs = xfs_btree_get_numrecs(left);
2005 if (cur->bc_ptrs[level] >= lrecs)
2006 goto out0;
2007
2008
2009 error = xfs_btree_read_buf_block(cur, &rptr, level, 0, &right, &rbp);
2010 if (error)
2011 goto error0;
2012
2013
2014 rrecs = xfs_btree_get_numrecs(right);
2015 if (rrecs == cur->bc_ops->get_maxrecs(cur, level))
2016 goto out0;
2017
2018 XFS_BTREE_STATS_INC(cur, rshift);
2019 XFS_BTREE_STATS_ADD(cur, moves, rrecs);
2020
2021
2022
2023
2024
2025 if (level > 0) {
2026
2027 union xfs_btree_key *lkp;
2028 union xfs_btree_ptr *lpp;
2029 union xfs_btree_ptr *rpp;
2030
2031 lkp = xfs_btree_key_addr(cur, lrecs, left);
2032 lpp = xfs_btree_ptr_addr(cur, lrecs, left);
2033 rkp = xfs_btree_key_addr(cur, 1, right);
2034 rpp = xfs_btree_ptr_addr(cur, 1, right);
2035
2036#ifdef DEBUG
2037 for (i = rrecs - 1; i >= 0; i--) {
2038 error = xfs_btree_check_ptr(cur, rpp, i, level);
2039 if (error)
2040 goto error0;
2041 }
2042#endif
2043
2044 xfs_btree_shift_keys(cur, rkp, 1, rrecs);
2045 xfs_btree_shift_ptrs(cur, rpp, 1, rrecs);
2046
2047#ifdef DEBUG
2048 error = xfs_btree_check_ptr(cur, lpp, 0, level);
2049 if (error)
2050 goto error0;
2051#endif
2052
2053
2054 xfs_btree_copy_keys(cur, rkp, lkp, 1);
2055 xfs_btree_copy_ptrs(cur, rpp, lpp, 1);
2056
2057 xfs_btree_log_keys(cur, rbp, 1, rrecs + 1);
2058 xfs_btree_log_ptrs(cur, rbp, 1, rrecs + 1);
2059
2060 ASSERT(cur->bc_ops->keys_inorder(cur, rkp,
2061 xfs_btree_key_addr(cur, 2, right)));
2062 } else {
2063
2064 union xfs_btree_rec *lrp;
2065 union xfs_btree_rec *rrp;
2066
2067 lrp = xfs_btree_rec_addr(cur, lrecs, left);
2068 rrp = xfs_btree_rec_addr(cur, 1, right);
2069
2070 xfs_btree_shift_recs(cur, rrp, 1, rrecs);
2071
2072
2073 xfs_btree_copy_recs(cur, rrp, lrp, 1);
2074 xfs_btree_log_recs(cur, rbp, 1, rrecs + 1);
2075
2076 cur->bc_ops->init_key_from_rec(&key, rrp);
2077 rkp = &key;
2078
2079 ASSERT(cur->bc_ops->recs_inorder(cur, rrp,
2080 xfs_btree_rec_addr(cur, 2, right)));
2081 }
2082
2083
2084
2085
2086 xfs_btree_set_numrecs(left, --lrecs);
2087 xfs_btree_log_block(cur, lbp, XFS_BB_NUMRECS);
2088
2089 xfs_btree_set_numrecs(right, ++rrecs);
2090 xfs_btree_log_block(cur, rbp, XFS_BB_NUMRECS);
2091
2092
2093
2094
2095
2096 error = xfs_btree_dup_cursor(cur, &tcur);
2097 if (error)
2098 goto error0;
2099 i = xfs_btree_lastrec(tcur, level);
2100 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
2101
2102 error = xfs_btree_increment(tcur, level, &i);
2103 if (error)
2104 goto error1;
2105
2106 error = xfs_btree_updkey(tcur, rkp, level + 1);
2107 if (error)
2108 goto error1;
2109
2110 xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR);
2111
2112 XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
2113 *stat = 1;
2114 return 0;
2115
2116out0:
2117 XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
2118 *stat = 0;
2119 return 0;
2120
2121error0:
2122 XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR);
2123 return error;
2124
2125error1:
2126 XFS_BTREE_TRACE_CURSOR(tcur, XBT_ERROR);
2127 xfs_btree_del_cursor(tcur, XFS_BTREE_ERROR);
2128 return error;
2129}
2130
2131
2132
2133
2134
2135
2136STATIC int
2137xfs_btree_split(
2138 struct xfs_btree_cur *cur,
2139 int level,
2140 union xfs_btree_ptr *ptrp,
2141 union xfs_btree_key *key,
2142 struct xfs_btree_cur **curp,
2143 int *stat)
2144{
2145 union xfs_btree_ptr lptr;
2146 struct xfs_buf *lbp;
2147 struct xfs_btree_block *left;
2148 union xfs_btree_ptr rptr;
2149 struct xfs_buf *rbp;
2150 struct xfs_btree_block *right;
2151 union xfs_btree_ptr rrptr;
2152 struct xfs_buf *rrbp;
2153 struct xfs_btree_block *rrblock;
2154 int lrecs;
2155 int rrecs;
2156 int src_index;
2157 int error;
2158#ifdef DEBUG
2159 int i;
2160#endif
2161
2162 XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY);
2163 XFS_BTREE_TRACE_ARGIPK(cur, level, *ptrp, key);
2164
2165 XFS_BTREE_STATS_INC(cur, split);
2166
2167
2168 left = xfs_btree_get_block(cur, level, &lbp);
2169
2170#ifdef DEBUG
2171 error = xfs_btree_check_block(cur, left, level, lbp);
2172 if (error)
2173 goto error0;
2174#endif
2175
2176 xfs_btree_buf_to_ptr(cur, lbp, &lptr);
2177
2178
2179 error = cur->bc_ops->alloc_block(cur, &lptr, &rptr, 1, stat);
2180 if (error)
2181 goto error0;
2182 if (*stat == 0)
2183 goto out0;
2184 XFS_BTREE_STATS_INC(cur, alloc);
2185
2186
2187 error = xfs_btree_get_buf_block(cur, &rptr, 0, &right, &rbp);
2188 if (error)
2189 goto error0;
2190
2191
2192 xfs_btree_init_block(cur, xfs_btree_get_level(left), 0, right);
2193
2194
2195
2196
2197
2198
2199 lrecs = xfs_btree_get_numrecs(left);
2200 rrecs = lrecs / 2;
2201 if ((lrecs & 1) && cur->bc_ptrs[level] <= rrecs + 1)
2202 rrecs++;
2203 src_index = (lrecs - rrecs + 1);
2204
2205 XFS_BTREE_STATS_ADD(cur, moves, rrecs);
2206
2207
2208
2209
2210
2211
2212 if (level > 0) {
2213
2214 union xfs_btree_key *lkp;
2215 union xfs_btree_ptr *lpp;
2216 union xfs_btree_key *rkp;
2217 union xfs_btree_ptr *rpp;
2218
2219 lkp = xfs_btree_key_addr(cur, src_index, left);
2220 lpp = xfs_btree_ptr_addr(cur, src_index, left);
2221 rkp = xfs_btree_key_addr(cur, 1, right);
2222 rpp = xfs_btree_ptr_addr(cur, 1, right);
2223
2224#ifdef DEBUG
2225 for (i = src_index; i < rrecs; i++) {
2226 error = xfs_btree_check_ptr(cur, lpp, i, level);
2227 if (error)
2228 goto error0;
2229 }
2230#endif
2231
2232 xfs_btree_copy_keys(cur, rkp, lkp, rrecs);
2233 xfs_btree_copy_ptrs(cur, rpp, lpp, rrecs);
2234
2235 xfs_btree_log_keys(cur, rbp, 1, rrecs);
2236 xfs_btree_log_ptrs(cur, rbp, 1, rrecs);
2237
2238
2239 xfs_btree_copy_keys(cur, key, rkp, 1);
2240 } else {
2241
2242 union xfs_btree_rec *lrp;
2243 union xfs_btree_rec *rrp;
2244
2245 lrp = xfs_btree_rec_addr(cur, src_index, left);
2246 rrp = xfs_btree_rec_addr(cur, 1, right);
2247
2248 xfs_btree_copy_recs(cur, rrp, lrp, rrecs);
2249 xfs_btree_log_recs(cur, rbp, 1, rrecs);
2250
2251 cur->bc_ops->init_key_from_rec(key,
2252 xfs_btree_rec_addr(cur, 1, right));
2253 }
2254
2255
2256
2257
2258
2259
2260 xfs_btree_get_sibling(cur, left, &rrptr, XFS_BB_RIGHTSIB);
2261 xfs_btree_set_sibling(cur, right, &rrptr, XFS_BB_RIGHTSIB);
2262 xfs_btree_set_sibling(cur, right, &lptr, XFS_BB_LEFTSIB);
2263 xfs_btree_set_sibling(cur, left, &rptr, XFS_BB_RIGHTSIB);
2264
2265 lrecs -= rrecs;
2266 xfs_btree_set_numrecs(left, lrecs);
2267 xfs_btree_set_numrecs(right, xfs_btree_get_numrecs(right) + rrecs);
2268
2269 xfs_btree_log_block(cur, rbp, XFS_BB_ALL_BITS);
2270 xfs_btree_log_block(cur, lbp, XFS_BB_NUMRECS | XFS_BB_RIGHTSIB);
2271
2272
2273
2274
2275
2276 if (!xfs_btree_ptr_is_null(cur, &rrptr)) {
2277 error = xfs_btree_read_buf_block(cur, &rrptr, level,
2278 0, &rrblock, &rrbp);
2279 if (error)
2280 goto error0;
2281 xfs_btree_set_sibling(cur, rrblock, &rptr, XFS_BB_LEFTSIB);
2282 xfs_btree_log_block(cur, rrbp, XFS_BB_LEFTSIB);
2283 }
2284
2285
2286
2287
2288
2289 if (cur->bc_ptrs[level] > lrecs + 1) {
2290 xfs_btree_setbuf(cur, level, rbp);
2291 cur->bc_ptrs[level] -= lrecs;
2292 }
2293
2294
2295
2296
2297 if (level + 1 < cur->bc_nlevels) {
2298 error = xfs_btree_dup_cursor(cur, curp);
2299 if (error)
2300 goto error0;
2301 (*curp)->bc_ptrs[level + 1]++;
2302 }
2303 *ptrp = rptr;
2304 XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
2305 *stat = 1;
2306 return 0;
2307out0:
2308 XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
2309 *stat = 0;
2310 return 0;
2311
2312error0:
2313 XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR);
2314 return error;
2315}
2316
2317
2318
2319
2320
2321int
2322xfs_btree_new_iroot(
2323 struct xfs_btree_cur *cur,
2324 int *logflags,
2325 int *stat)
2326{
2327 struct xfs_buf *cbp;
2328 struct xfs_btree_block *block;
2329 struct xfs_btree_block *cblock;
2330 union xfs_btree_key *ckp;
2331 union xfs_btree_ptr *cpp;
2332 union xfs_btree_key *kp;
2333 union xfs_btree_ptr *pp;
2334 union xfs_btree_ptr nptr;
2335 int level;
2336 int error;
2337#ifdef DEBUG
2338 int i;
2339#endif
2340
2341 XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY);
2342 XFS_BTREE_STATS_INC(cur, newroot);
2343
2344 ASSERT(cur->bc_flags & XFS_BTREE_ROOT_IN_INODE);
2345
2346 level = cur->bc_nlevels - 1;
2347
2348 block = xfs_btree_get_iroot(cur);
2349 pp = xfs_btree_ptr_addr(cur, 1, block);
2350
2351
2352 error = cur->bc_ops->alloc_block(cur, pp, &nptr, 1, stat);
2353 if (error)
2354 goto error0;
2355 if (*stat == 0) {
2356 XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
2357 return 0;
2358 }
2359 XFS_BTREE_STATS_INC(cur, alloc);
2360
2361
2362 error = xfs_btree_get_buf_block(cur, &nptr, 0, &cblock, &cbp);
2363 if (error)
2364 goto error0;
2365
2366 memcpy(cblock, block, xfs_btree_block_len(cur));
2367
2368 be16_add_cpu(&block->bb_level, 1);
2369 xfs_btree_set_numrecs(block, 1);
2370 cur->bc_nlevels++;
2371 cur->bc_ptrs[level + 1] = 1;
2372
2373 kp = xfs_btree_key_addr(cur, 1, block);
2374 ckp = xfs_btree_key_addr(cur, 1, cblock);
2375 xfs_btree_copy_keys(cur, ckp, kp, xfs_btree_get_numrecs(cblock));
2376
2377 cpp = xfs_btree_ptr_addr(cur, 1, cblock);
2378#ifdef DEBUG
2379 for (i = 0; i < be16_to_cpu(cblock->bb_numrecs); i++) {
2380 error = xfs_btree_check_ptr(cur, pp, i, level);
2381 if (error)
2382 goto error0;
2383 }
2384#endif
2385 xfs_btree_copy_ptrs(cur, cpp, pp, xfs_btree_get_numrecs(cblock));
2386
2387#ifdef DEBUG
2388 error = xfs_btree_check_ptr(cur, &nptr, 0, level);
2389 if (error)
2390 goto error0;
2391#endif
2392 xfs_btree_copy_ptrs(cur, pp, &nptr, 1);
2393
2394 xfs_iroot_realloc(cur->bc_private.b.ip,
2395 1 - xfs_btree_get_numrecs(cblock),
2396 cur->bc_private.b.whichfork);
2397
2398 xfs_btree_setbuf(cur, level, cbp);
2399
2400
2401
2402
2403
2404 xfs_btree_log_block(cur, cbp, XFS_BB_ALL_BITS);
2405 xfs_btree_log_keys(cur, cbp, 1, be16_to_cpu(cblock->bb_numrecs));
2406 xfs_btree_log_ptrs(cur, cbp, 1, be16_to_cpu(cblock->bb_numrecs));
2407
2408 *logflags |=
2409 XFS_ILOG_CORE | xfs_ilog_fbroot(cur->bc_private.b.whichfork);
2410 *stat = 1;
2411 XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
2412 return 0;
2413error0:
2414 XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR);
2415 return error;
2416}
2417
2418
2419
2420
2421STATIC int
2422xfs_btree_new_root(
2423 struct xfs_btree_cur *cur,
2424 int *stat)
2425{
2426 struct xfs_btree_block *block;
2427 struct xfs_buf *bp;
2428 int error;
2429 struct xfs_buf *lbp;
2430 struct xfs_btree_block *left;
2431 struct xfs_buf *nbp;
2432 struct xfs_btree_block *new;
2433 int nptr;
2434 struct xfs_buf *rbp;
2435 struct xfs_btree_block *right;
2436 union xfs_btree_ptr rptr;
2437 union xfs_btree_ptr lptr;
2438
2439 XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY);
2440 XFS_BTREE_STATS_INC(cur, newroot);
2441
2442
2443 cur->bc_ops->init_ptr_from_cur(cur, &rptr);
2444
2445
2446 error = cur->bc_ops->alloc_block(cur, &rptr, &lptr, 1, stat);
2447 if (error)
2448 goto error0;
2449 if (*stat == 0)
2450 goto out0;
2451 XFS_BTREE_STATS_INC(cur, alloc);
2452
2453
2454 error = xfs_btree_get_buf_block(cur, &lptr, 0, &new, &nbp);
2455 if (error)
2456 goto error0;
2457
2458
2459 cur->bc_ops->set_root(cur, &lptr, 1);
2460
2461
2462
2463
2464
2465
2466
2467 block = xfs_btree_get_block(cur, cur->bc_nlevels - 1, &bp);
2468
2469#ifdef DEBUG
2470 error = xfs_btree_check_block(cur, block, cur->bc_nlevels - 1, bp);
2471 if (error)
2472 goto error0;
2473#endif
2474
2475 xfs_btree_get_sibling(cur, block, &rptr, XFS_BB_RIGHTSIB);
2476 if (!xfs_btree_ptr_is_null(cur, &rptr)) {
2477
2478 lbp = bp;
2479 xfs_btree_buf_to_ptr(cur, lbp, &lptr);
2480 left = block;
2481 error = xfs_btree_read_buf_block(cur, &rptr,
2482 cur->bc_nlevels - 1, 0, &right, &rbp);
2483 if (error)
2484 goto error0;
2485 bp = rbp;
2486 nptr = 1;
2487 } else {
2488
2489 rbp = bp;
2490 xfs_btree_buf_to_ptr(cur, rbp, &rptr);
2491 right = block;
2492 xfs_btree_get_sibling(cur, right, &lptr, XFS_BB_LEFTSIB);
2493 error = xfs_btree_read_buf_block(cur, &lptr,
2494 cur->bc_nlevels - 1, 0, &left, &lbp);
2495 if (error)
2496 goto error0;
2497 bp = lbp;
2498 nptr = 2;
2499 }
2500
2501 xfs_btree_init_block(cur, cur->bc_nlevels, 2, new);
2502 xfs_btree_log_block(cur, nbp, XFS_BB_ALL_BITS);
2503 ASSERT(!xfs_btree_ptr_is_null(cur, &lptr) &&
2504 !xfs_btree_ptr_is_null(cur, &rptr));
2505
2506
2507 if (xfs_btree_get_level(left) > 0) {
2508 xfs_btree_copy_keys(cur,
2509 xfs_btree_key_addr(cur, 1, new),
2510 xfs_btree_key_addr(cur, 1, left), 1);
2511 xfs_btree_copy_keys(cur,
2512 xfs_btree_key_addr(cur, 2, new),
2513 xfs_btree_key_addr(cur, 1, right), 1);
2514 } else {
2515 cur->bc_ops->init_key_from_rec(
2516 xfs_btree_key_addr(cur, 1, new),
2517 xfs_btree_rec_addr(cur, 1, left));
2518 cur->bc_ops->init_key_from_rec(
2519 xfs_btree_key_addr(cur, 2, new),
2520 xfs_btree_rec_addr(cur, 1, right));
2521 }
2522 xfs_btree_log_keys(cur, nbp, 1, 2);
2523
2524
2525 xfs_btree_copy_ptrs(cur,
2526 xfs_btree_ptr_addr(cur, 1, new), &lptr, 1);
2527 xfs_btree_copy_ptrs(cur,
2528 xfs_btree_ptr_addr(cur, 2, new), &rptr, 1);
2529 xfs_btree_log_ptrs(cur, nbp, 1, 2);
2530
2531
2532 xfs_btree_setbuf(cur, cur->bc_nlevels, nbp);
2533 cur->bc_ptrs[cur->bc_nlevels] = nptr;
2534 cur->bc_nlevels++;
2535 XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
2536 *stat = 1;
2537 return 0;
2538error0:
2539 XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR);
2540 return error;
2541out0:
2542 XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
2543 *stat = 0;
2544 return 0;
2545}
2546
2547STATIC int
2548xfs_btree_make_block_unfull(
2549 struct xfs_btree_cur *cur,
2550 int level,
2551 int numrecs,
2552 int *oindex,
2553 int *index,
2554 union xfs_btree_ptr *nptr,
2555 struct xfs_btree_cur **ncur,
2556 union xfs_btree_rec *nrec,
2557 int *stat)
2558{
2559 union xfs_btree_key key;
2560 int error = 0;
2561
2562 if ((cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) &&
2563 level == cur->bc_nlevels - 1) {
2564 struct xfs_inode *ip = cur->bc_private.b.ip;
2565
2566 if (numrecs < cur->bc_ops->get_dmaxrecs(cur, level)) {
2567
2568
2569 xfs_iroot_realloc(ip, 1, cur->bc_private.b.whichfork);
2570 } else {
2571
2572 int logflags = 0;
2573
2574 error = xfs_btree_new_iroot(cur, &logflags, stat);
2575 if (error || *stat == 0)
2576 return error;
2577
2578 xfs_trans_log_inode(cur->bc_tp, ip, logflags);
2579 }
2580
2581 return 0;
2582 }
2583
2584
2585 error = xfs_btree_rshift(cur, level, stat);
2586 if (error || *stat)
2587 return error;
2588
2589
2590 error = xfs_btree_lshift(cur, level, stat);
2591 if (error)
2592 return error;
2593
2594 if (*stat) {
2595 *oindex = *index = cur->bc_ptrs[level];
2596 return 0;
2597 }
2598
2599
2600
2601
2602
2603
2604
2605 error = xfs_btree_split(cur, level, nptr, &key, ncur, stat);
2606 if (error || *stat == 0)
2607 return error;
2608
2609
2610 *index = cur->bc_ptrs[level];
2611 cur->bc_ops->init_rec_from_key(&key, nrec);
2612 return 0;
2613}
2614
2615
2616
2617
2618
2619STATIC int
2620xfs_btree_insrec(
2621 struct xfs_btree_cur *cur,
2622 int level,
2623 union xfs_btree_ptr *ptrp,
2624 union xfs_btree_rec *recp,
2625 struct xfs_btree_cur **curp,
2626 int *stat)
2627{
2628 struct xfs_btree_block *block;
2629 struct xfs_buf *bp;
2630 union xfs_btree_key key;
2631 union xfs_btree_ptr nptr;
2632 struct xfs_btree_cur *ncur;
2633 union xfs_btree_rec nrec;
2634 int optr;
2635 int ptr;
2636 int numrecs;
2637 int error;
2638#ifdef DEBUG
2639 int i;
2640#endif
2641
2642 XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY);
2643 XFS_BTREE_TRACE_ARGIPR(cur, level, *ptrp, recp);
2644
2645 ncur = NULL;
2646
2647
2648
2649
2650
2651 if (!(cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) &&
2652 (level >= cur->bc_nlevels)) {
2653 error = xfs_btree_new_root(cur, stat);
2654 xfs_btree_set_ptr_null(cur, ptrp);
2655
2656 XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
2657 return error;
2658 }
2659
2660
2661 ptr = cur->bc_ptrs[level];
2662 if (ptr == 0) {
2663 XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
2664 *stat = 0;
2665 return 0;
2666 }
2667
2668
2669 cur->bc_ops->init_key_from_rec(&key, recp);
2670
2671 optr = ptr;
2672
2673 XFS_BTREE_STATS_INC(cur, insrec);
2674
2675
2676 block = xfs_btree_get_block(cur, level, &bp);
2677 numrecs = xfs_btree_get_numrecs(block);
2678
2679#ifdef DEBUG
2680 error = xfs_btree_check_block(cur, block, level, bp);
2681 if (error)
2682 goto error0;
2683
2684
2685 if (ptr <= numrecs) {
2686 if (level == 0) {
2687 ASSERT(cur->bc_ops->recs_inorder(cur, recp,
2688 xfs_btree_rec_addr(cur, ptr, block)));
2689 } else {
2690 ASSERT(cur->bc_ops->keys_inorder(cur, &key,
2691 xfs_btree_key_addr(cur, ptr, block)));
2692 }
2693 }
2694#endif
2695
2696
2697
2698
2699
2700 xfs_btree_set_ptr_null(cur, &nptr);
2701 if (numrecs == cur->bc_ops->get_maxrecs(cur, level)) {
2702 error = xfs_btree_make_block_unfull(cur, level, numrecs,
2703 &optr, &ptr, &nptr, &ncur, &nrec, stat);
2704 if (error || *stat == 0)
2705 goto error0;
2706 }
2707
2708
2709
2710
2711
2712 block = xfs_btree_get_block(cur, level, &bp);
2713 numrecs = xfs_btree_get_numrecs(block);
2714
2715#ifdef DEBUG
2716 error = xfs_btree_check_block(cur, block, level, bp);
2717 if (error)
2718 return error;
2719#endif
2720
2721
2722
2723
2724
2725 XFS_BTREE_STATS_ADD(cur, moves, numrecs - ptr + 1);
2726
2727 if (level > 0) {
2728
2729 union xfs_btree_key *kp;
2730 union xfs_btree_ptr *pp;
2731
2732 kp = xfs_btree_key_addr(cur, ptr, block);
2733 pp = xfs_btree_ptr_addr(cur, ptr, block);
2734
2735#ifdef DEBUG
2736 for (i = numrecs - ptr; i >= 0; i--) {
2737 error = xfs_btree_check_ptr(cur, pp, i, level);
2738 if (error)
2739 return error;
2740 }
2741#endif
2742
2743 xfs_btree_shift_keys(cur, kp, 1, numrecs - ptr + 1);
2744 xfs_btree_shift_ptrs(cur, pp, 1, numrecs - ptr + 1);
2745
2746#ifdef DEBUG
2747 error = xfs_btree_check_ptr(cur, ptrp, 0, level);
2748 if (error)
2749 goto error0;
2750#endif
2751
2752
2753 xfs_btree_copy_keys(cur, kp, &key, 1);
2754 xfs_btree_copy_ptrs(cur, pp, ptrp, 1);
2755 numrecs++;
2756 xfs_btree_set_numrecs(block, numrecs);
2757 xfs_btree_log_ptrs(cur, bp, ptr, numrecs);
2758 xfs_btree_log_keys(cur, bp, ptr, numrecs);
2759#ifdef DEBUG
2760 if (ptr < numrecs) {
2761 ASSERT(cur->bc_ops->keys_inorder(cur, kp,
2762 xfs_btree_key_addr(cur, ptr + 1, block)));
2763 }
2764#endif
2765 } else {
2766
2767 union xfs_btree_rec *rp;
2768
2769 rp = xfs_btree_rec_addr(cur, ptr, block);
2770
2771 xfs_btree_shift_recs(cur, rp, 1, numrecs - ptr + 1);
2772
2773
2774 xfs_btree_copy_recs(cur, rp, recp, 1);
2775 xfs_btree_set_numrecs(block, ++numrecs);
2776 xfs_btree_log_recs(cur, bp, ptr, numrecs);
2777#ifdef DEBUG
2778 if (ptr < numrecs) {
2779 ASSERT(cur->bc_ops->recs_inorder(cur, rp,
2780 xfs_btree_rec_addr(cur, ptr + 1, block)));
2781 }
2782#endif
2783 }
2784
2785
2786 xfs_btree_log_block(cur, bp, XFS_BB_NUMRECS);
2787
2788
2789 if (optr == 1) {
2790 error = xfs_btree_updkey(cur, &key, level + 1);
2791 if (error)
2792 goto error0;
2793 }
2794
2795
2796
2797
2798
2799 if (xfs_btree_is_lastrec(cur, block, level)) {
2800 cur->bc_ops->update_lastrec(cur, block, recp,
2801 ptr, LASTREC_INSREC);
2802 }
2803
2804
2805
2806
2807
2808 *ptrp = nptr;
2809 if (!xfs_btree_ptr_is_null(cur, &nptr)) {
2810 *recp = nrec;
2811 *curp = ncur;
2812 }
2813
2814 XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
2815 *stat = 1;
2816 return 0;
2817
2818error0:
2819 XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR);
2820 return error;
2821}
2822
2823
2824
2825
2826
2827
2828
2829
2830int
2831xfs_btree_insert(
2832 struct xfs_btree_cur *cur,
2833 int *stat)
2834{
2835 int error;
2836 int i;
2837 int level;
2838 union xfs_btree_ptr nptr;
2839 struct xfs_btree_cur *ncur;
2840 struct xfs_btree_cur *pcur;
2841 union xfs_btree_rec rec;
2842
2843 level = 0;
2844 ncur = NULL;
2845 pcur = cur;
2846
2847 xfs_btree_set_ptr_null(cur, &nptr);
2848 cur->bc_ops->init_rec_from_cur(cur, &rec);
2849
2850
2851
2852
2853
2854
2855 do {
2856
2857
2858
2859
2860 error = xfs_btree_insrec(pcur, level, &nptr, &rec, &ncur, &i);
2861 if (error) {
2862 if (pcur != cur)
2863 xfs_btree_del_cursor(pcur, XFS_BTREE_ERROR);
2864 goto error0;
2865 }
2866
2867 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
2868 level++;
2869
2870
2871
2872
2873
2874
2875 if (pcur != cur &&
2876 (ncur || xfs_btree_ptr_is_null(cur, &nptr))) {
2877
2878 if (cur->bc_ops->update_cursor)
2879 cur->bc_ops->update_cursor(pcur, cur);
2880 cur->bc_nlevels = pcur->bc_nlevels;
2881 xfs_btree_del_cursor(pcur, XFS_BTREE_NOERROR);
2882 }
2883
2884 if (ncur) {
2885 pcur = ncur;
2886 ncur = NULL;
2887 }
2888 } while (!xfs_btree_ptr_is_null(cur, &nptr));
2889
2890 XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
2891 *stat = i;
2892 return 0;
2893error0:
2894 XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR);
2895 return error;
2896}
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906STATIC int
2907xfs_btree_kill_iroot(
2908 struct xfs_btree_cur *cur)
2909{
2910 int whichfork = cur->bc_private.b.whichfork;
2911 struct xfs_inode *ip = cur->bc_private.b.ip;
2912 struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork);
2913 struct xfs_btree_block *block;
2914 struct xfs_btree_block *cblock;
2915 union xfs_btree_key *kp;
2916 union xfs_btree_key *ckp;
2917 union xfs_btree_ptr *pp;
2918 union xfs_btree_ptr *cpp;
2919 struct xfs_buf *cbp;
2920 int level;
2921 int index;
2922 int numrecs;
2923#ifdef DEBUG
2924 union xfs_btree_ptr ptr;
2925 int i;
2926#endif
2927
2928 XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY);
2929
2930 ASSERT(cur->bc_flags & XFS_BTREE_ROOT_IN_INODE);
2931 ASSERT(cur->bc_nlevels > 1);
2932
2933
2934
2935
2936
2937 level = cur->bc_nlevels - 1;
2938 if (level == 1)
2939 goto out0;
2940
2941
2942
2943
2944 block = xfs_btree_get_iroot(cur);
2945 if (xfs_btree_get_numrecs(block) != 1)
2946 goto out0;
2947
2948 cblock = xfs_btree_get_block(cur, level - 1, &cbp);
2949 numrecs = xfs_btree_get_numrecs(cblock);
2950
2951
2952
2953
2954
2955
2956 if (numrecs > cur->bc_ops->get_dmaxrecs(cur, level))
2957 goto out0;
2958
2959 XFS_BTREE_STATS_INC(cur, killroot);
2960
2961#ifdef DEBUG
2962 xfs_btree_get_sibling(cur, block, &ptr, XFS_BB_LEFTSIB);
2963 ASSERT(xfs_btree_ptr_is_null(cur, &ptr));
2964 xfs_btree_get_sibling(cur, block, &ptr, XFS_BB_RIGHTSIB);
2965 ASSERT(xfs_btree_ptr_is_null(cur, &ptr));
2966#endif
2967
2968 index = numrecs - cur->bc_ops->get_maxrecs(cur, level);
2969 if (index) {
2970 xfs_iroot_realloc(cur->bc_private.b.ip, index,
2971 cur->bc_private.b.whichfork);
2972 block = ifp->if_broot;
2973 }
2974
2975 be16_add_cpu(&block->bb_numrecs, index);
2976 ASSERT(block->bb_numrecs == cblock->bb_numrecs);
2977
2978 kp = xfs_btree_key_addr(cur, 1, block);
2979 ckp = xfs_btree_key_addr(cur, 1, cblock);
2980 xfs_btree_copy_keys(cur, kp, ckp, numrecs);
2981
2982 pp = xfs_btree_ptr_addr(cur, 1, block);
2983 cpp = xfs_btree_ptr_addr(cur, 1, cblock);
2984#ifdef DEBUG
2985 for (i = 0; i < numrecs; i++) {
2986 int error;
2987
2988 error = xfs_btree_check_ptr(cur, cpp, i, level - 1);
2989 if (error) {
2990 XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR);
2991 return error;
2992 }
2993 }
2994#endif
2995 xfs_btree_copy_ptrs(cur, pp, cpp, numrecs);
2996
2997 cur->bc_ops->free_block(cur, cbp);
2998 XFS_BTREE_STATS_INC(cur, free);
2999
3000 cur->bc_bufs[level - 1] = NULL;
3001 be16_add_cpu(&block->bb_level, -1);
3002 xfs_trans_log_inode(cur->bc_tp, ip,
3003 XFS_ILOG_CORE | xfs_ilog_fbroot(cur->bc_private.b.whichfork));
3004 cur->bc_nlevels--;
3005out0:
3006 XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
3007 return 0;
3008}
3009
3010
3011
3012
3013STATIC int
3014xfs_btree_kill_root(
3015 struct xfs_btree_cur *cur,
3016 struct xfs_buf *bp,
3017 int level,
3018 union xfs_btree_ptr *newroot)
3019{
3020 int error;
3021
3022 XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY);
3023 XFS_BTREE_STATS_INC(cur, killroot);
3024
3025
3026
3027
3028
3029 cur->bc_ops->set_root(cur, newroot, -1);
3030
3031 error = cur->bc_ops->free_block(cur, bp);
3032 if (error) {
3033 XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR);
3034 return error;
3035 }
3036
3037 XFS_BTREE_STATS_INC(cur, free);
3038
3039 cur->bc_bufs[level] = NULL;
3040 cur->bc_ra[level] = 0;
3041 cur->bc_nlevels--;
3042
3043 XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
3044 return 0;
3045}
3046
3047STATIC int
3048xfs_btree_dec_cursor(
3049 struct xfs_btree_cur *cur,
3050 int level,
3051 int *stat)
3052{
3053 int error;
3054 int i;
3055
3056 if (level > 0) {
3057 error = xfs_btree_decrement(cur, level, &i);
3058 if (error)
3059 return error;
3060 }
3061
3062 XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
3063 *stat = 1;
3064 return 0;
3065}
3066
3067
3068
3069
3070
3071
3072
3073STATIC int
3074xfs_btree_delrec(
3075 struct xfs_btree_cur *cur,
3076 int level,
3077 int *stat)
3078{
3079 struct xfs_btree_block *block;
3080 union xfs_btree_ptr cptr;
3081 struct xfs_buf *bp;
3082 int error;
3083 int i;
3084 union xfs_btree_key key;
3085 union xfs_btree_key *keyp = &key;
3086 union xfs_btree_ptr lptr;
3087 struct xfs_buf *lbp;
3088 struct xfs_btree_block *left;
3089 int lrecs = 0;
3090 int ptr;
3091 union xfs_btree_ptr rptr;
3092 struct xfs_buf *rbp;
3093 struct xfs_btree_block *right;
3094 struct xfs_btree_block *rrblock;
3095 struct xfs_buf *rrbp;
3096 int rrecs = 0;
3097 struct xfs_btree_cur *tcur;
3098 int numrecs;
3099
3100 XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY);
3101 XFS_BTREE_TRACE_ARGI(cur, level);
3102
3103 tcur = NULL;
3104
3105
3106 ptr = cur->bc_ptrs[level];
3107 if (ptr == 0) {
3108 XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
3109 *stat = 0;
3110 return 0;
3111 }
3112
3113
3114 block = xfs_btree_get_block(cur, level, &bp);
3115 numrecs = xfs_btree_get_numrecs(block);
3116
3117#ifdef DEBUG
3118 error = xfs_btree_check_block(cur, block, level, bp);
3119 if (error)
3120 goto error0;
3121#endif
3122
3123
3124 if (ptr > numrecs) {
3125 XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
3126 *stat = 0;
3127 return 0;
3128 }
3129
3130 XFS_BTREE_STATS_INC(cur, delrec);
3131 XFS_BTREE_STATS_ADD(cur, moves, numrecs - ptr);
3132
3133
3134 if (level > 0) {
3135
3136 union xfs_btree_key *lkp;
3137 union xfs_btree_ptr *lpp;
3138
3139 lkp = xfs_btree_key_addr(cur, ptr + 1, block);
3140 lpp = xfs_btree_ptr_addr(cur, ptr + 1, block);
3141
3142#ifdef DEBUG
3143 for (i = 0; i < numrecs - ptr; i++) {
3144 error = xfs_btree_check_ptr(cur, lpp, i, level);
3145 if (error)
3146 goto error0;
3147 }
3148#endif
3149
3150 if (ptr < numrecs) {
3151 xfs_btree_shift_keys(cur, lkp, -1, numrecs - ptr);
3152 xfs_btree_shift_ptrs(cur, lpp, -1, numrecs - ptr);
3153 xfs_btree_log_keys(cur, bp, ptr, numrecs - 1);
3154 xfs_btree_log_ptrs(cur, bp, ptr, numrecs - 1);
3155 }
3156
3157
3158
3159
3160
3161 if (ptr == 1)
3162 keyp = xfs_btree_key_addr(cur, 1, block);
3163 } else {
3164
3165 if (ptr < numrecs) {
3166 xfs_btree_shift_recs(cur,
3167 xfs_btree_rec_addr(cur, ptr + 1, block),
3168 -1, numrecs - ptr);
3169 xfs_btree_log_recs(cur, bp, ptr, numrecs - 1);
3170 }
3171
3172
3173
3174
3175
3176 if (ptr == 1) {
3177 cur->bc_ops->init_key_from_rec(&key,
3178 xfs_btree_rec_addr(cur, 1, block));
3179 keyp = &key;
3180 }
3181 }
3182
3183
3184
3185
3186 xfs_btree_set_numrecs(block, --numrecs);
3187 xfs_btree_log_block(cur, bp, XFS_BB_NUMRECS);
3188
3189
3190
3191
3192
3193 if (xfs_btree_is_lastrec(cur, block, level)) {
3194 cur->bc_ops->update_lastrec(cur, block, NULL,
3195 ptr, LASTREC_DELREC);
3196 }
3197
3198
3199
3200
3201
3202
3203 if (level == cur->bc_nlevels - 1) {
3204 if (cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) {
3205 xfs_iroot_realloc(cur->bc_private.b.ip, -1,
3206 cur->bc_private.b.whichfork);
3207
3208 error = xfs_btree_kill_iroot(cur);
3209 if (error)
3210 goto error0;
3211
3212 error = xfs_btree_dec_cursor(cur, level, stat);
3213 if (error)
3214 goto error0;
3215 *stat = 1;
3216 return 0;
3217 }
3218
3219
3220
3221
3222
3223
3224 if (numrecs == 1 && level > 0) {
3225 union xfs_btree_ptr *pp;
3226
3227
3228
3229
3230 pp = xfs_btree_ptr_addr(cur, 1, block);
3231 error = xfs_btree_kill_root(cur, bp, level, pp);
3232 if (error)
3233 goto error0;
3234 } else if (level > 0) {
3235 error = xfs_btree_dec_cursor(cur, level, stat);
3236 if (error)
3237 goto error0;
3238 }
3239 *stat = 1;
3240 return 0;
3241 }
3242
3243
3244
3245
3246
3247 if (ptr == 1) {
3248 error = xfs_btree_updkey(cur, keyp, level + 1);
3249 if (error)
3250 goto error0;
3251 }
3252
3253
3254
3255
3256
3257 if (numrecs >= cur->bc_ops->get_minrecs(cur, level)) {
3258 error = xfs_btree_dec_cursor(cur, level, stat);
3259 if (error)
3260 goto error0;
3261 return 0;
3262 }
3263
3264
3265
3266
3267
3268
3269 xfs_btree_get_sibling(cur, block, &rptr, XFS_BB_RIGHTSIB);
3270 xfs_btree_get_sibling(cur, block, &lptr, XFS_BB_LEFTSIB);
3271
3272 if (cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) {
3273
3274
3275
3276
3277
3278 if (xfs_btree_ptr_is_null(cur, &rptr) &&
3279 xfs_btree_ptr_is_null(cur, &lptr) &&
3280 level == cur->bc_nlevels - 2) {
3281 error = xfs_btree_kill_iroot(cur);
3282 if (!error)
3283 error = xfs_btree_dec_cursor(cur, level, stat);
3284 if (error)
3285 goto error0;
3286 return 0;
3287 }
3288 }
3289
3290 ASSERT(!xfs_btree_ptr_is_null(cur, &rptr) ||
3291 !xfs_btree_ptr_is_null(cur, &lptr));
3292
3293
3294
3295
3296
3297 error = xfs_btree_dup_cursor(cur, &tcur);
3298 if (error)
3299 goto error0;
3300
3301
3302
3303
3304
3305 if (!xfs_btree_ptr_is_null(cur, &rptr)) {
3306
3307
3308
3309
3310 i = xfs_btree_lastrec(tcur, level);
3311 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
3312
3313 error = xfs_btree_increment(tcur, level, &i);
3314 if (error)
3315 goto error0;
3316 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
3317
3318 i = xfs_btree_lastrec(tcur, level);
3319 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
3320
3321
3322 right = xfs_btree_get_block(tcur, level, &rbp);
3323#ifdef DEBUG
3324 error = xfs_btree_check_block(tcur, right, level, rbp);
3325 if (error)
3326 goto error0;
3327#endif
3328
3329 xfs_btree_get_sibling(tcur, right, &cptr, XFS_BB_LEFTSIB);
3330
3331
3332
3333
3334
3335
3336 if (xfs_btree_get_numrecs(right) - 1 >=
3337 cur->bc_ops->get_minrecs(tcur, level)) {
3338 error = xfs_btree_lshift(tcur, level, &i);
3339 if (error)
3340 goto error0;
3341 if (i) {
3342 ASSERT(xfs_btree_get_numrecs(block) >=
3343 cur->bc_ops->get_minrecs(tcur, level));
3344
3345 xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR);
3346 tcur = NULL;
3347
3348 error = xfs_btree_dec_cursor(cur, level, stat);
3349 if (error)
3350 goto error0;
3351 return 0;
3352 }
3353 }
3354
3355
3356
3357
3358
3359
3360 rrecs = xfs_btree_get_numrecs(right);
3361 if (!xfs_btree_ptr_is_null(cur, &lptr)) {
3362 i = xfs_btree_firstrec(tcur, level);
3363 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
3364
3365 error = xfs_btree_decrement(tcur, level, &i);
3366 if (error)
3367 goto error0;
3368 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
3369 }
3370 }
3371
3372
3373
3374
3375
3376 if (!xfs_btree_ptr_is_null(cur, &lptr)) {
3377
3378
3379
3380
3381 i = xfs_btree_firstrec(tcur, level);
3382 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
3383
3384 error = xfs_btree_decrement(tcur, level, &i);
3385 if (error)
3386 goto error0;
3387 i = xfs_btree_firstrec(tcur, level);
3388 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
3389
3390
3391 left = xfs_btree_get_block(tcur, level, &lbp);
3392#ifdef DEBUG
3393 error = xfs_btree_check_block(cur, left, level, lbp);
3394 if (error)
3395 goto error0;
3396#endif
3397
3398 xfs_btree_get_sibling(tcur, left, &cptr, XFS_BB_RIGHTSIB);
3399
3400
3401
3402
3403
3404
3405 if (xfs_btree_get_numrecs(left) - 1 >=
3406 cur->bc_ops->get_minrecs(tcur, level)) {
3407 error = xfs_btree_rshift(tcur, level, &i);
3408 if (error)
3409 goto error0;
3410 if (i) {
3411 ASSERT(xfs_btree_get_numrecs(block) >=
3412 cur->bc_ops->get_minrecs(tcur, level));
3413 xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR);
3414 tcur = NULL;
3415 if (level == 0)
3416 cur->bc_ptrs[0]++;
3417 XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
3418 *stat = 1;
3419 return 0;
3420 }
3421 }
3422
3423
3424
3425
3426
3427 lrecs = xfs_btree_get_numrecs(left);
3428 }
3429
3430
3431 xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR);
3432 tcur = NULL;
3433
3434
3435 ASSERT(!xfs_btree_ptr_is_null(cur, &cptr));
3436
3437 if (!xfs_btree_ptr_is_null(cur, &lptr) &&
3438 lrecs + xfs_btree_get_numrecs(block) <=
3439 cur->bc_ops->get_maxrecs(cur, level)) {
3440
3441
3442
3443
3444 rptr = cptr;
3445 right = block;
3446 rbp = bp;
3447 error = xfs_btree_read_buf_block(cur, &lptr, level,
3448 0, &left, &lbp);
3449 if (error)
3450 goto error0;
3451
3452
3453
3454
3455 } else if (!xfs_btree_ptr_is_null(cur, &rptr) &&
3456 rrecs + xfs_btree_get_numrecs(block) <=
3457 cur->bc_ops->get_maxrecs(cur, level)) {
3458
3459
3460
3461
3462 lptr = cptr;
3463 left = block;
3464 lbp = bp;
3465 error = xfs_btree_read_buf_block(cur, &rptr, level,
3466 0, &right, &rbp);
3467 if (error)
3468 goto error0;
3469
3470
3471
3472
3473
3474 } else {
3475 error = xfs_btree_dec_cursor(cur, level, stat);
3476 if (error)
3477 goto error0;
3478 return 0;
3479 }
3480
3481 rrecs = xfs_btree_get_numrecs(right);
3482 lrecs = xfs_btree_get_numrecs(left);
3483
3484
3485
3486
3487
3488 XFS_BTREE_STATS_ADD(cur, moves, rrecs);
3489 if (level > 0) {
3490
3491 union xfs_btree_key *lkp;
3492 union xfs_btree_ptr *lpp;
3493 union xfs_btree_key *rkp;
3494 union xfs_btree_ptr *rpp;
3495
3496 lkp = xfs_btree_key_addr(cur, lrecs + 1, left);
3497 lpp = xfs_btree_ptr_addr(cur, lrecs + 1, left);
3498 rkp = xfs_btree_key_addr(cur, 1, right);
3499 rpp = xfs_btree_ptr_addr(cur, 1, right);
3500#ifdef DEBUG
3501 for (i = 1; i < rrecs; i++) {
3502 error = xfs_btree_check_ptr(cur, rpp, i, level);
3503 if (error)
3504 goto error0;
3505 }
3506#endif
3507 xfs_btree_copy_keys(cur, lkp, rkp, rrecs);
3508 xfs_btree_copy_ptrs(cur, lpp, rpp, rrecs);
3509
3510 xfs_btree_log_keys(cur, lbp, lrecs + 1, lrecs + rrecs);
3511 xfs_btree_log_ptrs(cur, lbp, lrecs + 1, lrecs + rrecs);
3512 } else {
3513
3514 union xfs_btree_rec *lrp;
3515 union xfs_btree_rec *rrp;
3516
3517 lrp = xfs_btree_rec_addr(cur, lrecs + 1, left);
3518 rrp = xfs_btree_rec_addr(cur, 1, right);
3519
3520 xfs_btree_copy_recs(cur, lrp, rrp, rrecs);
3521 xfs_btree_log_recs(cur, lbp, lrecs + 1, lrecs + rrecs);
3522 }
3523
3524 XFS_BTREE_STATS_INC(cur, join);
3525
3526
3527
3528
3529
3530 xfs_btree_set_numrecs(left, lrecs + rrecs);
3531 xfs_btree_get_sibling(cur, right, &cptr, XFS_BB_RIGHTSIB),
3532 xfs_btree_set_sibling(cur, left, &cptr, XFS_BB_RIGHTSIB);
3533 xfs_btree_log_block(cur, lbp, XFS_BB_NUMRECS | XFS_BB_RIGHTSIB);
3534
3535
3536 xfs_btree_get_sibling(cur, left, &cptr, XFS_BB_RIGHTSIB);
3537 if (!xfs_btree_ptr_is_null(cur, &cptr)) {
3538 error = xfs_btree_read_buf_block(cur, &cptr, level,
3539 0, &rrblock, &rrbp);
3540 if (error)
3541 goto error0;
3542 xfs_btree_set_sibling(cur, rrblock, &lptr, XFS_BB_LEFTSIB);
3543 xfs_btree_log_block(cur, rrbp, XFS_BB_LEFTSIB);
3544 }
3545
3546
3547 error = cur->bc_ops->free_block(cur, rbp);
3548 if (error)
3549 goto error0;
3550 XFS_BTREE_STATS_INC(cur, free);
3551
3552
3553
3554
3555
3556 if (bp != lbp) {
3557 cur->bc_bufs[level] = lbp;
3558 cur->bc_ptrs[level] += lrecs;
3559 cur->bc_ra[level] = 0;
3560 }
3561
3562
3563
3564
3565 else if ((cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) ||
3566 (level + 1 < cur->bc_nlevels)) {
3567 error = xfs_btree_increment(cur, level + 1, &i);
3568 if (error)
3569 goto error0;
3570 }
3571
3572
3573
3574
3575
3576
3577
3578 if (level > 0)
3579 cur->bc_ptrs[level]--;
3580
3581 XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
3582
3583 *stat = 2;
3584 return 0;
3585
3586error0:
3587 XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR);
3588 if (tcur)
3589 xfs_btree_del_cursor(tcur, XFS_BTREE_ERROR);
3590 return error;
3591}
3592
3593
3594
3595
3596
3597
3598int
3599xfs_btree_delete(
3600 struct xfs_btree_cur *cur,
3601 int *stat)
3602{
3603 int error;
3604 int level;
3605 int i;
3606
3607 XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY);
3608
3609
3610
3611
3612
3613
3614
3615 for (level = 0, i = 2; i == 2; level++) {
3616 error = xfs_btree_delrec(cur, level, &i);
3617 if (error)
3618 goto error0;
3619 }
3620
3621 if (i == 0) {
3622 for (level = 1; level < cur->bc_nlevels; level++) {
3623 if (cur->bc_ptrs[level] == 0) {
3624 error = xfs_btree_decrement(cur, level, &i);
3625 if (error)
3626 goto error0;
3627 break;
3628 }
3629 }
3630 }
3631
3632 XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
3633 *stat = i;
3634 return 0;
3635error0:
3636 XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR);
3637 return error;
3638}
3639
3640
3641
3642
3643int
3644xfs_btree_get_rec(
3645 struct xfs_btree_cur *cur,
3646 union xfs_btree_rec **recp,
3647 int *stat)
3648{
3649 struct xfs_btree_block *block;
3650 struct xfs_buf *bp;
3651 int ptr;
3652#ifdef DEBUG
3653 int error;
3654#endif
3655
3656 ptr = cur->bc_ptrs[0];
3657 block = xfs_btree_get_block(cur, 0, &bp);
3658
3659#ifdef DEBUG
3660 error = xfs_btree_check_block(cur, block, 0, bp);
3661 if (error)
3662 return error;
3663#endif
3664
3665
3666
3667
3668 if (ptr > xfs_btree_get_numrecs(block) || ptr <= 0) {
3669 *stat = 0;
3670 return 0;
3671 }
3672
3673
3674
3675
3676 *recp = xfs_btree_rec_addr(cur, ptr, block);
3677 *stat = 1;
3678 return 0;
3679}
3680