2 * Copyright (c) 2000-2001 Silicon Graphics, Inc. All Rights Reserved.
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 * Further, this software is distributed without any warranty that it is
13 * free of the rightful claim of any third person regarding infringement
14 * or the like. Any license provided herein, whether implied or
15 * otherwise, applies only to this software file. Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write the Free Software Foundation, Inc., 59
21 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
28 * For further information regarding this notice, see:
30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
39 #include "err_protos.h"
41 #define ALLOC_NUM_EXTS 100
44 * paranoia -- account for any weird padding, 64/32-bit alignment, etc.
46 typedef struct extent_alloc_rec
{
48 extent_tree_node_t extents
[ALLOC_NUM_EXTS
];
51 typedef struct rt_extent_alloc_rec
{
53 rt_extent_tree_node_t extents
[ALLOC_NUM_EXTS
];
54 } rt_extent_alloc_rec_t
;
57 * note: there are 4 sets of incore things handled here:
58 * block bitmaps, extent trees, uncertain inode list,
59 * and inode tree. The tree-based code uses the AVL
60 * tree package used by the IRIX kernel VM code
61 * (sys/avl.h). The inode list code uses the same records
62 * as the inode tree code for convenience. The bitmaps
63 * and bitmap operators are mostly macros defined in incore.h.
64 * There are one of everything per AG except for extent
65 * trees. There's one duplicate extent tree, one bno and
66 * one bcnt extent tree per AG. Not all of the above exist
67 * through all phases. The duplicate extent tree gets trashed
68 * at the end of phase 4. The bno/bcnt trees don't appear until
69 * phase 5. The uncertain inode list goes away at the end of
70 * phase 3. The inode tree and bno/bnct trees go away after phase 5.
72 typedef struct ext_flist_s
{
73 extent_tree_node_t
*list
;
77 static ext_flist_t ext_flist
;
79 typedef struct rt_ext_flist_s
{
80 rt_extent_tree_node_t
*list
;
84 static rt_ext_flist_t rt_ext_flist
;
86 static avl64tree_desc_t
*rt_ext_tree_ptr
; /* dup extent tree for rt */
88 static avltree_desc_t
**extent_tree_ptrs
; /* array of extent tree ptrs */
89 /* one per ag for dups */
90 static avltree_desc_t
**extent_bno_ptrs
; /*
91 * array of extent tree ptrs
92 * one per ag for free extents
93 * sorted by starting block
96 static avltree_desc_t
**extent_bcnt_ptrs
; /*
97 * array of extent tree ptrs
98 * one per ag for free extents
103 * list of allocated "blocks" for easy freeing later
105 static ba_rec_t
*ba_list
;
106 static ba_rec_t
*rt_ba_list
;
109 * extent tree stuff is avl trees of duplicate extents,
110 * sorted in order by block number. there is one tree per ag.
113 static extent_tree_node_t
*
114 mk_extent_tree_nodes(xfs_agblock_t new_startblock
,
115 xfs_extlen_t new_blockcount
, extent_state_t new_state
)
118 extent_tree_node_t
*new;
119 extent_alloc_rec_t
*rec
;
121 if (ext_flist
.cnt
== 0) {
122 ASSERT(ext_flist
.list
== NULL
);
124 if ((rec
= malloc(sizeof(extent_alloc_rec_t
))) == NULL
)
126 _("couldn't allocate new extent descriptors.\n"));
128 record_allocation(&rec
->alloc_rec
, ba_list
);
130 new = &rec
->extents
[0];
132 for (i
= 0; i
< ALLOC_NUM_EXTS
; i
++) {
133 new->avl_node
.avl_nextino
= (avlnode_t
*)
135 ext_flist
.list
= new;
141 ASSERT(ext_flist
.list
!= NULL
);
143 new = ext_flist
.list
;
144 ext_flist
.list
= (extent_tree_node_t
*) new->avl_node
.avl_nextino
;
146 new->avl_node
.avl_nextino
= NULL
;
148 /* initialize node */
150 new->ex_startblock
= new_startblock
;
151 new->ex_blockcount
= new_blockcount
;
152 new->ex_state
= new_state
;
159 release_extent_tree_node(extent_tree_node_t
*node
)
161 node
->avl_node
.avl_nextino
= (avlnode_t
*) ext_flist
.list
;
162 ext_flist
.list
= node
;
169 * routines to recycle all nodes in a tree. it walks the tree
170 * and puts all nodes back on the free list so the nodes can be
171 * reused. the duplicate and bno/bcnt extent trees for each AG
172 * are recycled after they're no longer needed to save memory
175 release_extent_tree(avltree_desc_t
*tree
)
177 extent_tree_node_t
*ext
;
178 extent_tree_node_t
*tmp
;
179 extent_tree_node_t
*lext
;
180 extent_tree_node_t
*ltmp
;
182 if (tree
->avl_firstino
== NULL
)
185 ext
= (extent_tree_node_t
*) tree
->avl_firstino
;
187 while (ext
!= NULL
) {
188 tmp
= (extent_tree_node_t
*) ext
->avl_node
.avl_nextino
;
191 * ext->next is guaranteed to be set only in bcnt trees
193 if (ext
->next
!= NULL
) {
195 while (lext
!= NULL
) {
197 release_extent_tree_node(lext
);
202 release_extent_tree_node(ext
);
206 tree
->avl_root
= tree
->avl_firstino
= NULL
;
212 * top-level (visible) routines
215 release_dup_extent_tree(xfs_agnumber_t agno
)
217 release_extent_tree(extent_tree_ptrs
[agno
]);
223 release_agbno_extent_tree(xfs_agnumber_t agno
)
225 release_extent_tree(extent_bno_ptrs
[agno
]);
231 release_agbcnt_extent_tree(xfs_agnumber_t agno
)
233 release_extent_tree(extent_bcnt_ptrs
[agno
]);
239 * the next 4 routines manage the trees of free extents -- 2 trees
240 * per AG. The first tree is sorted by block number. The second
241 * tree is sorted by extent size. This is the bno tree.
244 add_bno_extent(xfs_agnumber_t agno
, xfs_agblock_t startblock
,
245 xfs_extlen_t blockcount
)
247 extent_tree_node_t
*ext
;
249 ASSERT(extent_bno_ptrs
!= NULL
);
250 ASSERT(extent_bno_ptrs
[agno
] != NULL
);
252 ext
= mk_extent_tree_nodes(startblock
, blockcount
, XR_E_FREE
);
254 if (avl_insert(extent_bno_ptrs
[agno
], (avlnode_t
*) ext
) == NULL
) {
255 do_error(_("duplicate bno extent range\n"));
260 findfirst_bno_extent(xfs_agnumber_t agno
)
262 ASSERT(extent_bno_ptrs
!= NULL
);
263 ASSERT(extent_bno_ptrs
[agno
] != NULL
);
265 return((extent_tree_node_t
*) extent_bno_ptrs
[agno
]->avl_firstino
);
269 find_bno_extent(xfs_agnumber_t agno
, xfs_agblock_t startblock
)
271 ASSERT(extent_bno_ptrs
!= NULL
);
272 ASSERT(extent_bno_ptrs
[agno
] != NULL
);
274 return((extent_tree_node_t
*) avl_find(extent_bno_ptrs
[agno
],
279 * delete a node that's in the tree (pointer obtained by a find routine)
282 get_bno_extent(xfs_agnumber_t agno
, extent_tree_node_t
*ext
)
284 ASSERT(extent_bno_ptrs
!= NULL
);
285 ASSERT(extent_bno_ptrs
[agno
] != NULL
);
287 avl_delete(extent_bno_ptrs
[agno
], &ext
->avl_node
);
293 * normalizing constant for bcnt size -> address conversion (see avl ops)
294 * used by the AVL tree code to convert sizes and must be used when
295 * doing an AVL search in the tree (e.g. avl_findrange(s))
297 #define MAXBCNT 0xFFFFFFFF
298 #define BCNT_ADDR(cnt) ((unsigned int) MAXBCNT - (cnt))
301 * the next 4 routines manage the trees of free extents -- 2 trees
302 * per AG. The first tree is sorted by block number. The second
303 * tree is sorted by extent size. This is the bcnt tree.
306 add_bcnt_extent(xfs_agnumber_t agno
, xfs_agblock_t startblock
,
307 xfs_extlen_t blockcount
)
309 extent_tree_node_t
*ext
, *prev
, *current
, *top
;
310 xfs_agblock_t tmp_startblock
;
311 xfs_extlen_t tmp_blockcount
;
312 extent_state_t tmp_state
;
314 ASSERT(extent_bcnt_ptrs
!= NULL
);
315 ASSERT(extent_bcnt_ptrs
[agno
] != NULL
);
317 ext
= mk_extent_tree_nodes(startblock
, blockcount
, XR_E_FREE
);
319 ASSERT(ext
->next
== NULL
);
322 fprintf(stderr
, "adding bcnt: agno = %d, start = %u, count = %u\n",
323 agno
, startblock
, blockcount
);
325 if ((current
= (extent_tree_node_t
*) avl_find(extent_bcnt_ptrs
[agno
],
326 blockcount
)) != NULL
) {
328 * avl tree code doesn't handle dups so insert
329 * onto linked list in increasing startblock order
331 top
= prev
= current
;
332 while (current
!= NULL
&&
333 startblock
> current
->ex_startblock
) {
335 current
= current
->next
;
338 if (top
== current
) {
341 * swap the values of to-be-inserted element
342 * and the values of the head of the list.
343 * then insert as the 2nd element on the list.
345 * see the comment in get_bcnt_extent()
346 * as to why we have to do this.
348 tmp_startblock
= top
->ex_startblock
;
349 tmp_blockcount
= top
->ex_blockcount
;
350 tmp_state
= top
->ex_state
;
352 top
->ex_startblock
= ext
->ex_startblock
;
353 top
->ex_blockcount
= ext
->ex_blockcount
;
354 top
->ex_state
= ext
->ex_state
;
356 ext
->ex_startblock
= tmp_startblock
;
357 ext
->ex_blockcount
= tmp_blockcount
;
358 ext
->ex_state
= tmp_state
;
370 if (avl_insert(extent_bcnt_ptrs
[agno
], (avlnode_t
*) ext
) == NULL
) {
371 do_error(_(": duplicate bno extent range\n"));
378 findfirst_bcnt_extent(xfs_agnumber_t agno
)
380 ASSERT(extent_bcnt_ptrs
!= NULL
);
381 ASSERT(extent_bcnt_ptrs
[agno
] != NULL
);
383 return((extent_tree_node_t
*) extent_bcnt_ptrs
[agno
]->avl_firstino
);
387 findbiggest_bcnt_extent(xfs_agnumber_t agno
)
389 extern avlnode_t
*avl_lastino(avlnode_t
*root
);
391 ASSERT(extent_bcnt_ptrs
!= NULL
);
392 ASSERT(extent_bcnt_ptrs
[agno
] != NULL
);
394 return((extent_tree_node_t
*) avl_lastino(extent_bcnt_ptrs
[agno
]->avl_root
));
398 findnext_bcnt_extent(xfs_agnumber_t agno
, extent_tree_node_t
*ext
)
402 if (ext
->next
!= NULL
) {
403 ASSERT(ext
->ex_blockcount
== ext
->next
->ex_blockcount
);
404 ASSERT(ext
->ex_startblock
< ext
->next
->ex_startblock
);
408 * have to look at the top of the list to get the
409 * correct avl_nextino pointer since that pointer
410 * is maintained and altered by the AVL code.
412 nextino
= avl_find(extent_bcnt_ptrs
[agno
], ext
->ex_blockcount
);
413 ASSERT(nextino
!= NULL
);
414 if (nextino
->avl_nextino
!= NULL
) {
415 ASSERT(ext
->ex_blockcount
< ((extent_tree_node_t
*)
416 nextino
->avl_nextino
)->ex_blockcount
);
418 return((extent_tree_node_t
*) nextino
->avl_nextino
);
423 * this is meant to be called after you walk the bno tree to
424 * determine exactly which extent you want (so you'll know the
425 * desired value for startblock when you call this routine).
428 get_bcnt_extent(xfs_agnumber_t agno
, xfs_agblock_t startblock
,
429 xfs_extlen_t blockcount
)
431 extent_tree_node_t
*ext
, *prev
, *top
;
432 xfs_agblock_t tmp_startblock
;
433 xfs_extlen_t tmp_blockcount
;
434 extent_state_t tmp_state
;
437 ASSERT(extent_bcnt_ptrs
!= NULL
);
438 ASSERT(extent_bcnt_ptrs
[agno
] != NULL
);
440 if ((ext
= (extent_tree_node_t
*) avl_find(extent_bcnt_ptrs
[agno
],
441 blockcount
)) == NULL
)
446 if (ext
->next
!= NULL
) {
448 * pull it off the list
450 while (ext
!= NULL
&& startblock
!= ext
->ex_startblock
) {
457 * this node is linked into the tree so we
458 * swap the core values so we can delete
459 * the next item on the list instead of
460 * the head of the list. This is because
461 * the rest of the tree undoubtedly has
462 * pointers to the piece of memory that
463 * is the head of the list so pulling
464 * the item out of the list and hence
465 * the avl tree would be a bad idea.
467 * (cheaper than the alternative, a tree
468 * delete of this node followed by a tree
469 * insert of the next node on the list).
471 tmp_startblock
= ext
->next
->ex_startblock
;
472 tmp_blockcount
= ext
->next
->ex_blockcount
;
473 tmp_state
= ext
->next
->ex_state
;
475 ext
->next
->ex_startblock
= ext
->ex_startblock
;
476 ext
->next
->ex_blockcount
= ext
->ex_blockcount
;
477 ext
->next
->ex_state
= ext
->ex_state
;
479 ext
->ex_startblock
= tmp_startblock
;
480 ext
->ex_blockcount
= tmp_blockcount
;
481 ext
->ex_state
= tmp_state
;
487 * now, a simple list deletion
489 prev
->next
= ext
->next
;
493 * no list, just one node. simply delete
495 avl_delete(extent_bcnt_ptrs
[agno
], &ext
->avl_node
);
498 ASSERT(ext
->ex_startblock
== startblock
);
499 ASSERT(ext
->ex_blockcount
== blockcount
);
504 * the next 2 routines manage the trees of duplicate extents -- 1 tree
508 add_dup_extent(xfs_agnumber_t agno
, xfs_agblock_t startblock
,
509 xfs_extlen_t blockcount
)
511 extent_tree_node_t
*first
, *last
, *ext
, *next_ext
;
512 xfs_agblock_t new_startblock
;
513 xfs_extlen_t new_blockcount
;
515 ASSERT(agno
< glob_agcount
);
518 fprintf(stderr
, "Adding dup extent - %d/%d %d\n", agno
, startblock
, blockcount
);
520 avl_findranges(extent_tree_ptrs
[agno
], startblock
- 1,
521 startblock
+ blockcount
+ 1,
522 (avlnode_t
**) &first
, (avlnode_t
**) &last
);
524 * find adjacent and overlapping extent blocks
526 if (first
== NULL
&& last
== NULL
) {
527 /* nothing, just make and insert new extent */
529 ext
= mk_extent_tree_nodes(startblock
, blockcount
, XR_E_MULT
);
531 if (avl_insert(extent_tree_ptrs
[agno
],
532 (avlnode_t
*) ext
) == NULL
) {
533 do_error(_("duplicate extent range\n"));
539 ASSERT(first
!= NULL
&& last
!= NULL
);
542 * find the new composite range, delete old extent nodes
545 new_startblock
= startblock
;
546 new_blockcount
= blockcount
;
549 ext
!= (extent_tree_node_t
*) last
->avl_node
.avl_nextino
;
552 * preserve the next inorder node
554 next_ext
= (extent_tree_node_t
*) ext
->avl_node
.avl_nextino
;
556 * just bail if the new extent is contained within an old one
558 if (ext
->ex_startblock
<= startblock
&&
559 ext
->ex_blockcount
>= blockcount
)
562 * now check for overlaps and adjacent extents
564 if (ext
->ex_startblock
+ ext
->ex_blockcount
>= startblock
565 || ext
->ex_startblock
<= startblock
+ blockcount
) {
567 if (ext
->ex_startblock
< new_startblock
)
568 new_startblock
= ext
->ex_startblock
;
570 if (ext
->ex_startblock
+ ext
->ex_blockcount
>
571 new_startblock
+ new_blockcount
)
572 new_blockcount
= ext
->ex_startblock
+
576 avl_delete(extent_tree_ptrs
[agno
], (avlnode_t
*) ext
);
581 ext
= mk_extent_tree_nodes(new_startblock
, new_blockcount
, XR_E_MULT
);
583 if (avl_insert(extent_tree_ptrs
[agno
], (avlnode_t
*) ext
) == NULL
) {
584 do_error(_("duplicate extent range\n"));
591 * returns 1 if block is a dup, 0 if not
595 search_dup_extent(xfs_mount_t
*mp
, xfs_agnumber_t agno
, xfs_agblock_t agbno
)
597 ASSERT(agno
< glob_agcount
);
599 if (avl_findrange(extent_tree_ptrs
[agno
], agbno
) != NULL
)
605 static __psunsigned_t
606 avl_ext_start(avlnode_t
*node
)
608 return((__psunsigned_t
)
609 ((extent_tree_node_t
*) node
)->ex_startblock
);
612 static __psunsigned_t
613 avl_ext_end(avlnode_t
*node
)
615 return((__psunsigned_t
) (
616 ((extent_tree_node_t
*) node
)->ex_startblock
+
617 ((extent_tree_node_t
*) node
)->ex_blockcount
));
621 * convert size to an address for the AVL tree code -- the bigger the size,
622 * the lower the address so the biggest extent will be first in the tree
624 static __psunsigned_t
625 avl_ext_bcnt_start(avlnode_t
*node
)
628 return((__psunsigned_t) (BCNT_ADDR(((extent_tree_node_t *)
629 node)->ex_blockcount)));
631 return((__psunsigned_t
) ((extent_tree_node_t
*)node
)->ex_blockcount
);
634 static __psunsigned_t
635 avl_ext_bcnt_end(avlnode_t
*node
)
638 return((__psunsigned_t) (BCNT_ADDR(((extent_tree_node_t *)
639 node)->ex_blockcount)));
641 return((__psunsigned_t
) ((extent_tree_node_t
*)node
)->ex_blockcount
);
644 avlops_t avl_extent_bcnt_tree_ops
= {
649 avlops_t avl_extent_tree_ops
= {
655 * for real-time extents -- have to dup code since realtime extent
656 * startblocks can be 64-bit values.
658 static rt_extent_tree_node_t
*
659 mk_rt_extent_tree_nodes(xfs_drtbno_t new_startblock
,
660 xfs_extlen_t new_blockcount
, extent_state_t new_state
)
663 rt_extent_tree_node_t
*new;
664 rt_extent_alloc_rec_t
*rec
;
666 if (rt_ext_flist
.cnt
== 0) {
667 ASSERT(rt_ext_flist
.list
== NULL
);
669 if ((rec
= malloc(sizeof(rt_extent_alloc_rec_t
))) == NULL
)
671 _("couldn't allocate new extent descriptors.\n"));
673 record_allocation(&rec
->alloc_rec
, rt_ba_list
);
675 new = &rec
->extents
[0];
677 for (i
= 0; i
< ALLOC_NUM_EXTS
; i
++) {
678 new->avl_node
.avl_nextino
= (avlnode_t
*)
680 rt_ext_flist
.list
= new;
686 ASSERT(rt_ext_flist
.list
!= NULL
);
688 new = rt_ext_flist
.list
;
689 rt_ext_flist
.list
= (rt_extent_tree_node_t
*) new->avl_node
.avl_nextino
;
691 new->avl_node
.avl_nextino
= NULL
;
693 /* initialize node */
695 new->rt_startblock
= new_startblock
;
696 new->rt_blockcount
= new_blockcount
;
697 new->rt_state
= new_state
;
704 release_rt_extent_tree_node(rt_extent_tree_node_t
*node
)
706 node
->avl_node
.avl_nextino
= (avlnode_t
*) rt_ext_flist
.list
;
707 rt_ext_flist
.list
= node
;
714 release_rt_extent_tree()
716 extent_tree_node_t
*ext
;
717 extent_tree_node_t
*tmp
;
718 extent_tree_node_t
*lext
;
719 extent_tree_node_t
*ltmp
;
720 avl64tree_desc_t
*tree
;
722 tree
= rt_extent_tree_ptr
;
724 if (tree
->avl_firstino
== NULL
)
727 ext
= (extent_tree_node_t
*) tree
->avl_firstino
;
729 while (ext
!= NULL
) {
730 tmp
= (extent_tree_node_t
*) ext
->avl_node
.avl_nextino
;
731 release_rt_extent_tree_node(ext
);
735 tree
->avl_root
= tree
->avl_firstino
= NULL
;
742 * don't need release functions for realtime tree teardown
743 * since we only have one tree, not one per AG
747 free_rt_dup_extent_tree(xfs_mount_t
*mp
)
749 ASSERT(mp
->m_sb
.sb_rblocks
!= 0);
751 free_allocations(rt_ba_list
);
752 free(rt_ext_tree_ptr
);
755 rt_ext_tree_ptr
= NULL
;
761 * add a duplicate real-time extent
764 add_rt_dup_extent(xfs_drtbno_t startblock
, xfs_extlen_t blockcount
)
766 rt_extent_tree_node_t
*first
, *last
, *ext
, *next_ext
;
767 xfs_drtbno_t new_startblock
;
768 xfs_extlen_t new_blockcount
;
770 avl64_findranges(rt_ext_tree_ptr
, startblock
- 1,
771 startblock
+ blockcount
+ 1,
772 (avl64node_t
**) &first
, (avl64node_t
**) &last
);
774 * find adjacent and overlapping extent blocks
776 if (first
== NULL
&& last
== NULL
) {
777 /* nothing, just make and insert new extent */
779 ext
= mk_rt_extent_tree_nodes(startblock
,
780 blockcount
, XR_E_MULT
);
782 if (avl64_insert(rt_ext_tree_ptr
,
783 (avl64node_t
*) ext
) == NULL
) {
784 do_error(_("duplicate extent range\n"));
790 ASSERT(first
!= NULL
&& last
!= NULL
);
793 * find the new composite range, delete old extent nodes
796 new_startblock
= startblock
;
797 new_blockcount
= blockcount
;
800 ext
!= (rt_extent_tree_node_t
*) last
->avl_node
.avl_nextino
;
803 * preserve the next inorder node
805 next_ext
= (rt_extent_tree_node_t
*) ext
->avl_node
.avl_nextino
;
807 * just bail if the new extent is contained within an old one
809 if (ext
->rt_startblock
<= startblock
&&
810 ext
->rt_blockcount
>= blockcount
)
813 * now check for overlaps and adjacent extents
815 if (ext
->rt_startblock
+ ext
->rt_blockcount
>= startblock
816 || ext
->rt_startblock
<= startblock
+ blockcount
) {
818 if (ext
->rt_startblock
< new_startblock
)
819 new_startblock
= ext
->rt_startblock
;
821 if (ext
->rt_startblock
+ ext
->rt_blockcount
>
822 new_startblock
+ new_blockcount
)
823 new_blockcount
= ext
->rt_startblock
+
827 avl64_delete(rt_ext_tree_ptr
, (avl64node_t
*) ext
);
832 ext
= mk_rt_extent_tree_nodes(new_startblock
,
833 new_blockcount
, XR_E_MULT
);
835 if (avl64_insert(rt_ext_tree_ptr
, (avl64node_t
*) ext
) == NULL
) {
836 do_error(_("duplicate extent range\n"));
843 * returns 1 if block is a dup, 0 if not
847 search_rt_dup_extent(xfs_mount_t
*mp
, xfs_drtbno_t bno
)
849 if (avl64_findrange(rt_ext_tree_ptr
, bno
) != NULL
)
856 avl64_rt_ext_start(avl64node_t
*node
)
858 return(((rt_extent_tree_node_t
*) node
)->rt_startblock
);
862 avl64_ext_end(avl64node_t
*node
)
864 return(((rt_extent_tree_node_t
*) node
)->rt_startblock
+
865 ((rt_extent_tree_node_t
*) node
)->rt_blockcount
);
868 avl64ops_t avl64_extent_tree_ops
= {
874 incore_ext_init(xfs_mount_t
*mp
)
877 xfs_agnumber_t agcount
= mp
->m_sb
.sb_agcount
;
882 if ((extent_tree_ptrs
= malloc(agcount
*
883 sizeof(avltree_desc_t
*))) == NULL
)
885 _("couldn't malloc dup extent tree descriptor table\n"));
887 if ((extent_bno_ptrs
= malloc(agcount
*
888 sizeof(avltree_desc_t
*))) == NULL
)
890 _("couldn't malloc free by-bno extent tree descriptor table\n"));
892 if ((extent_bcnt_ptrs
= malloc(agcount
*
893 sizeof(avltree_desc_t
*))) == NULL
)
895 _("couldn't malloc free by-bcnt extent tree descriptor table\n"));
897 for (i
= 0; i
< agcount
; i
++) {
898 if ((extent_tree_ptrs
[i
] =
899 malloc(sizeof(avltree_desc_t
))) == NULL
)
901 _("couldn't malloc dup extent tree descriptor\n"));
902 if ((extent_bno_ptrs
[i
] =
903 malloc(sizeof(avltree_desc_t
))) == NULL
)
905 _("couldn't malloc bno extent tree descriptor\n"));
906 if ((extent_bcnt_ptrs
[i
] =
907 malloc(sizeof(avltree_desc_t
))) == NULL
)
909 _("couldn't malloc bcnt extent tree descriptor\n"));
912 for (i
= 0; i
< agcount
; i
++) {
913 avl_init_tree(extent_tree_ptrs
[i
], &avl_extent_tree_ops
);
914 avl_init_tree(extent_bno_ptrs
[i
], &avl_extent_tree_ops
);
915 avl_init_tree(extent_bcnt_ptrs
[i
], &avl_extent_bcnt_tree_ops
);
918 if ((rt_ext_tree_ptr
= malloc(sizeof(avltree_desc_t
))) == NULL
)
919 do_error(_("couldn't malloc dup rt extent tree descriptor\n"));
921 avl64_init_tree(rt_ext_tree_ptr
, &avl64_extent_tree_ops
);
924 ext_flist
.list
= NULL
;
930 * this routine actually frees all the memory used to track per-AG trees
933 incore_ext_teardown(xfs_mount_t
*mp
)
937 free_allocations(ba_list
);
939 for (i
= 0; i
< mp
->m_sb
.sb_agcount
; i
++) {
940 free(extent_tree_ptrs
[i
]);
941 free(extent_bno_ptrs
[i
]);
942 free(extent_bcnt_ptrs
[i
]);
945 free(extent_bcnt_ptrs
);
946 free(extent_bno_ptrs
);
947 free(extent_tree_ptrs
);
949 extent_bcnt_ptrs
= extent_bno_ptrs
= extent_tree_ptrs
= NULL
;
955 count_extents(xfs_agnumber_t agno
, avltree_desc_t
*tree
, int whichtree
)
957 extent_tree_node_t
*node
;
960 node
= (extent_tree_node_t
*) tree
->avl_firstino
;
962 while (node
!= NULL
) {
965 node
= findnext_bcnt_extent(agno
, node
);
967 node
= findnext_bno_extent(node
);
974 count_bno_extents_blocks(xfs_agnumber_t agno
, uint
*numblocks
)
977 extent_tree_node_t
*node
;
980 ASSERT(agno
< glob_agcount
);
984 node
= (extent_tree_node_t
*) extent_bno_ptrs
[agno
]->avl_firstino
;
986 while (node
!= NULL
) {
987 nblocks
+= node
->ex_blockcount
;
989 node
= findnext_bno_extent(node
);
992 *numblocks
= nblocks
;
997 count_bno_extents(xfs_agnumber_t agno
)
999 ASSERT(agno
< glob_agcount
);
1000 return(count_extents(agno
, extent_bno_ptrs
[agno
], 0));
1004 count_bcnt_extents(xfs_agnumber_t agno
)
1006 ASSERT(agno
< glob_agcount
);
1007 return(count_extents(agno
, extent_bcnt_ptrs
[agno
], 1));