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