2 * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26 #include "err_protos.h"
29 * array of inode tree ptrs, one per ag
31 avltree_desc_t
**inode_tree_ptrs
;
34 * ditto for uncertain inodes
36 static avltree_desc_t
**inode_uncertain_tree_ptrs
;
38 /* memory optimised nlink counting for all inodes */
41 alloc_nlink_array(__uint8_t nlink_size
)
45 ptr
= calloc(XFS_INODES_PER_CHUNK
, nlink_size
);
47 do_error(_("could not allocate nlink array\n"));
52 nlink_grow_8_to_16(ino_tree_node_t
*irec
)
54 __uint16_t
*new_nlinks
;
57 irec
->nlink_size
= sizeof(__uint16_t
);
59 new_nlinks
= alloc_nlink_array(irec
->nlink_size
);
60 for (i
= 0; i
< XFS_INODES_PER_CHUNK
; i
++)
61 new_nlinks
[i
] = irec
->disk_nlinks
.un8
[i
];
62 free(irec
->disk_nlinks
.un8
);
63 irec
->disk_nlinks
.un16
= new_nlinks
;
65 if (full_ino_ex_data
) {
66 new_nlinks
= alloc_nlink_array(irec
->nlink_size
);
67 for (i
= 0; i
< XFS_INODES_PER_CHUNK
; i
++) {
69 irec
->ino_un
.ex_data
->counted_nlinks
.un8
[i
];
71 free(irec
->ino_un
.ex_data
->counted_nlinks
.un8
);
72 irec
->ino_un
.ex_data
->counted_nlinks
.un16
= new_nlinks
;
77 nlink_grow_16_to_32(ino_tree_node_t
*irec
)
79 __uint32_t
*new_nlinks
;
82 irec
->nlink_size
= sizeof(__uint32_t
);
84 new_nlinks
= alloc_nlink_array(irec
->nlink_size
);
85 for (i
= 0; i
< XFS_INODES_PER_CHUNK
; i
++)
86 new_nlinks
[i
] = irec
->disk_nlinks
.un16
[i
];
87 free(irec
->disk_nlinks
.un16
);
88 irec
->disk_nlinks
.un32
= new_nlinks
;
90 if (full_ino_ex_data
) {
91 new_nlinks
= alloc_nlink_array(irec
->nlink_size
);
93 for (i
= 0; i
< XFS_INODES_PER_CHUNK
; i
++) {
95 irec
->ino_un
.ex_data
->counted_nlinks
.un16
[i
];
97 free(irec
->ino_un
.ex_data
->counted_nlinks
.un16
);
98 irec
->ino_un
.ex_data
->counted_nlinks
.un32
= new_nlinks
;
102 void add_inode_ref(struct ino_tree_node
*irec
, int ino_offset
)
104 ASSERT(irec
->ino_un
.ex_data
!= NULL
);
106 switch (irec
->nlink_size
) {
107 case sizeof(__uint8_t
):
108 if (irec
->ino_un
.ex_data
->counted_nlinks
.un8
[ino_offset
] < 0xff) {
109 irec
->ino_un
.ex_data
->counted_nlinks
.un8
[ino_offset
]++;
112 nlink_grow_8_to_16(irec
);
114 case sizeof(__uint16_t
):
115 if (irec
->ino_un
.ex_data
->counted_nlinks
.un16
[ino_offset
] < 0xffff) {
116 irec
->ino_un
.ex_data
->counted_nlinks
.un16
[ino_offset
]++;
119 nlink_grow_16_to_32(irec
);
121 case sizeof(__uint32_t
):
122 irec
->ino_un
.ex_data
->counted_nlinks
.un32
[ino_offset
]++;
129 void drop_inode_ref(struct ino_tree_node
*irec
, int ino_offset
)
133 ASSERT(irec
->ino_un
.ex_data
!= NULL
);
135 switch (irec
->nlink_size
) {
136 case sizeof(__uint8_t
):
137 ASSERT(irec
->ino_un
.ex_data
->counted_nlinks
.un8
[ino_offset
] > 0);
138 refs
= --irec
->ino_un
.ex_data
->counted_nlinks
.un8
[ino_offset
];
140 case sizeof(__uint16_t
):
141 ASSERT(irec
->ino_un
.ex_data
->counted_nlinks
.un16
[ino_offset
] > 0);
142 refs
= --irec
->ino_un
.ex_data
->counted_nlinks
.un16
[ino_offset
];
144 case sizeof(__uint32_t
):
145 ASSERT(irec
->ino_un
.ex_data
->counted_nlinks
.un32
[ino_offset
] > 0);
146 refs
= --irec
->ino_un
.ex_data
->counted_nlinks
.un32
[ino_offset
];
153 irec
->ino_un
.ex_data
->ino_reached
&= ~IREC_MASK(ino_offset
);
156 __uint32_t
num_inode_references(struct ino_tree_node
*irec
, int ino_offset
)
158 ASSERT(irec
->ino_un
.ex_data
!= NULL
);
160 switch (irec
->nlink_size
) {
161 case sizeof(__uint8_t
):
162 return irec
->ino_un
.ex_data
->counted_nlinks
.un8
[ino_offset
];
163 case sizeof(__uint16_t
):
164 return irec
->ino_un
.ex_data
->counted_nlinks
.un16
[ino_offset
];
165 case sizeof(__uint32_t
):
166 return irec
->ino_un
.ex_data
->counted_nlinks
.un32
[ino_offset
];
173 void set_inode_disk_nlinks(struct ino_tree_node
*irec
, int ino_offset
,
176 switch (irec
->nlink_size
) {
177 case sizeof(__uint8_t
):
179 irec
->disk_nlinks
.un8
[ino_offset
] = nlinks
;
182 nlink_grow_8_to_16(irec
);
184 case sizeof(__uint16_t
):
185 if (nlinks
< 0xffff) {
186 irec
->disk_nlinks
.un16
[ino_offset
] = nlinks
;
189 nlink_grow_16_to_32(irec
);
191 case sizeof(__uint32_t
):
192 irec
->disk_nlinks
.un32
[ino_offset
] = nlinks
;
199 __uint32_t
get_inode_disk_nlinks(struct ino_tree_node
*irec
, int ino_offset
)
201 switch (irec
->nlink_size
) {
202 case sizeof(__uint8_t
):
203 return irec
->disk_nlinks
.un8
[ino_offset
];
204 case sizeof(__uint16_t
):
205 return irec
->disk_nlinks
.un16
[ino_offset
];
206 case sizeof(__uint32_t
):
207 return irec
->disk_nlinks
.un32
[ino_offset
];
216 struct xfs_mount
*mp
)
220 if (!xfs_sb_version_hasftype(&mp
->m_sb
))
223 ptr
= calloc(XFS_INODES_PER_CHUNK
, sizeof(*ptr
));
225 do_error(_("could not allocate ftypes array\n"));
230 * Next is the uncertain inode list -- a sorted (in ascending order)
231 * list of inode records sorted on the starting inode number. There
232 * is one list per ag.
236 * Common code for creating inode records for use by trees and lists.
237 * called only from add_inodes and add_inodes_uncertain
239 * IMPORTANT: all inodes (inode records) start off as free and
242 static struct ino_tree_node
*
244 struct xfs_mount
*mp
,
245 xfs_agino_t starting_ino
)
247 struct ino_tree_node
*irec
;
249 irec
= malloc(sizeof(*irec
));
251 do_error(_("inode map malloc failed\n"));
253 irec
->avl_node
.avl_nextino
= NULL
;
254 irec
->avl_node
.avl_forw
= NULL
;
255 irec
->avl_node
.avl_back
= NULL
;
257 irec
->ino_startnum
= starting_ino
;
258 irec
->ino_confirmed
= 0;
259 irec
->ino_isa_dir
= 0;
260 irec
->ir_free
= (xfs_inofree_t
) - 1;
262 irec
->ino_un
.ex_data
= NULL
;
263 irec
->nlink_size
= sizeof(__uint8_t
);
264 irec
->disk_nlinks
.un8
= alloc_nlink_array(irec
->nlink_size
);
265 irec
->ftypes
= alloc_ftypes_array(mp
);
270 free_nlink_array(union ino_nlink nlinks
, __uint8_t nlink_size
)
272 switch (nlink_size
) {
273 case sizeof(__uint8_t
):
276 case sizeof(__uint16_t
):
279 case sizeof(__uint32_t
):
289 struct ino_tree_node
*irec
)
291 irec
->avl_node
.avl_nextino
= NULL
;
292 irec
->avl_node
.avl_forw
= NULL
;
293 irec
->avl_node
.avl_back
= NULL
;
295 free_nlink_array(irec
->disk_nlinks
, irec
->nlink_size
);
296 if (irec
->ino_un
.ex_data
!= NULL
) {
297 if (full_ino_ex_data
) {
298 free(irec
->ino_un
.ex_data
->parents
);
299 free_nlink_array(irec
->ino_un
.ex_data
->counted_nlinks
,
302 free(irec
->ino_un
.ex_data
);
311 * last referenced cache for uncertain inodes
313 static ino_tree_node_t
**last_rec
;
316 * ok, the uncertain inodes are a set of trees just like the
317 * good inodes but all starting inode records are (arbitrarily)
318 * aligned on XFS_CHUNK_PER_INODE boundaries to prevent overlaps.
319 * this means we may have partials records in the tree (e.g. records
320 * without 64 confirmed uncertain inodes). Tough.
322 * free is set to 1 if the inode is thought to be free, 0 if used
325 add_aginode_uncertain(
326 struct xfs_mount
*mp
,
331 ino_tree_node_t
*ino_rec
;
335 ASSERT(agno
< glob_agcount
);
336 ASSERT(last_rec
!= NULL
);
338 s_ino
= rounddown(ino
, XFS_INODES_PER_CHUNK
);
341 * check for a cache hit
343 if (last_rec
[agno
] != NULL
&& last_rec
[agno
]->ino_startnum
== s_ino
) {
344 offset
= ino
- s_ino
;
346 set_inode_free(last_rec
[agno
], offset
);
348 set_inode_used(last_rec
[agno
], offset
);
354 * check to see if record containing inode is already in the tree.
357 ino_rec
= (ino_tree_node_t
*)
358 avl_findrange(inode_uncertain_tree_ptrs
[agno
], s_ino
);
360 ino_rec
= alloc_ino_node(mp
, s_ino
);
362 if (!avl_insert(inode_uncertain_tree_ptrs
[agno
],
365 _("add_aginode_uncertain - duplicate inode range\n"));
369 set_inode_free(ino_rec
, ino
- s_ino
);
371 set_inode_used(ino_rec
, ino
- s_ino
);
376 last_rec
[agno
] = ino_rec
;
380 * like add_aginode_uncertain() only it needs an xfs_mount_t *
381 * to perform the inode number conversion.
384 add_inode_uncertain(xfs_mount_t
*mp
, xfs_ino_t ino
, int free
)
386 add_aginode_uncertain(mp
, XFS_INO_TO_AGNO(mp
, ino
),
387 XFS_INO_TO_AGINO(mp
, ino
), free
);
391 * pull the indicated inode record out of the uncertain inode tree
394 get_uncertain_inode_rec(struct xfs_mount
*mp
, xfs_agnumber_t agno
,
395 ino_tree_node_t
*ino_rec
)
397 ASSERT(inode_tree_ptrs
!= NULL
);
398 ASSERT(agno
< mp
->m_sb
.sb_agcount
);
399 ASSERT(inode_tree_ptrs
[agno
] != NULL
);
401 avl_delete(inode_uncertain_tree_ptrs
[agno
], &ino_rec
->avl_node
);
403 ino_rec
->avl_node
.avl_nextino
= NULL
;
404 ino_rec
->avl_node
.avl_forw
= NULL
;
405 ino_rec
->avl_node
.avl_back
= NULL
;
409 findfirst_uncertain_inode_rec(xfs_agnumber_t agno
)
411 return((ino_tree_node_t
*)
412 inode_uncertain_tree_ptrs
[agno
]->avl_firstino
);
416 find_uncertain_inode_rec(xfs_agnumber_t agno
, xfs_agino_t ino
)
418 return((ino_tree_node_t
*)
419 avl_findrange(inode_uncertain_tree_ptrs
[agno
], ino
));
423 clear_uncertain_ino_cache(xfs_agnumber_t agno
)
425 last_rec
[agno
] = NULL
;
430 * Next comes the inode trees. One per AG, AVL trees of inode records, each
431 * inode record tracking 64 inodes
435 * Set up an inode tree record for a group of inodes that will include the
438 * This does NOT do error-check for duplicate records. The caller is
439 * responsible for checking that. Ino must be the start of an
440 * XFS_INODES_PER_CHUNK (64) inode chunk
442 * Each inode resides in a 64-inode chunk which can be part one or more chunks
443 * (MAX(64, inodes-per-block). The fs allocates in chunks (as opposed to 1
444 * chunk) when a block can hold more than one chunk (inodes per block > 64).
445 * Allocating in one chunk pieces causes us problems when it takes more than
446 * one fs block to contain an inode chunk because the chunks can start on
447 * *any* block boundary. So we assume that the caller has a clue because at
448 * this level, we don't.
450 static struct ino_tree_node
*
452 struct xfs_mount
*mp
,
456 struct ino_tree_node
*irec
;
458 irec
= alloc_ino_node(mp
, agino
);
459 if (!avl_insert(inode_tree_ptrs
[agno
], &irec
->avl_node
))
460 do_warn(_("add_inode - duplicate inode range\n"));
465 * pull the indicated inode record out of the inode tree
468 get_inode_rec(struct xfs_mount
*mp
, xfs_agnumber_t agno
, ino_tree_node_t
*ino_rec
)
470 ASSERT(inode_tree_ptrs
!= NULL
);
471 ASSERT(agno
< mp
->m_sb
.sb_agcount
);
472 ASSERT(inode_tree_ptrs
[agno
] != NULL
);
474 avl_delete(inode_tree_ptrs
[agno
], &ino_rec
->avl_node
);
476 ino_rec
->avl_node
.avl_nextino
= NULL
;
477 ino_rec
->avl_node
.avl_forw
= NULL
;
478 ino_rec
->avl_node
.avl_back
= NULL
;
482 * free the designated inode record (return it to the free pool)
486 free_inode_rec(xfs_agnumber_t agno
, ino_tree_node_t
*ino_rec
)
488 free_ino_tree_node(ino_rec
);
492 find_inode_rec_range(struct xfs_mount
*mp
, xfs_agnumber_t agno
,
493 xfs_agino_t start_ino
, xfs_agino_t end_ino
,
494 ino_tree_node_t
**first
, ino_tree_node_t
**last
)
496 *first
= *last
= NULL
;
499 * Is the AG inside the file system ?
501 if (agno
< mp
->m_sb
.sb_agcount
)
502 avl_findranges(inode_tree_ptrs
[agno
], start_ino
,
503 end_ino
, (avlnode_t
**) first
, (avlnode_t
**) last
);
507 * if ino doesn't exist, it must be properly aligned -- on a
508 * filesystem block boundary or XFS_INODES_PER_CHUNK boundary,
509 * whichever alignment is larger.
512 set_inode_used_alloc(struct xfs_mount
*mp
, xfs_agnumber_t agno
, xfs_agino_t ino
)
514 ino_tree_node_t
*ino_rec
;
517 * check alignment -- the only way to detect this
518 * is too see if the chunk overlaps another chunk
519 * already in the tree
521 ino_rec
= add_inode(mp
, agno
, ino
);
523 ASSERT(ino_rec
!= NULL
);
524 ASSERT(ino
>= ino_rec
->ino_startnum
&&
525 ino
- ino_rec
->ino_startnum
< XFS_INODES_PER_CHUNK
);
527 set_inode_used(ino_rec
, ino
- ino_rec
->ino_startnum
);
533 set_inode_free_alloc(struct xfs_mount
*mp
, xfs_agnumber_t agno
, xfs_agino_t ino
)
535 ino_tree_node_t
*ino_rec
;
537 ino_rec
= add_inode(mp
, agno
, ino
);
539 ASSERT(ino_rec
!= NULL
);
540 ASSERT(ino
>= ino_rec
->ino_startnum
&&
541 ino
- ino_rec
->ino_startnum
< XFS_INODES_PER_CHUNK
);
543 set_inode_free(ino_rec
, ino
- ino_rec
->ino_startnum
);
549 print_inode_list_int(xfs_agnumber_t agno
, int uncertain
)
551 ino_tree_node_t
*ino_rec
;
554 fprintf(stderr
, _("good inode list is --\n"));
555 ino_rec
= findfirst_inode_rec(agno
);
557 fprintf(stderr
, _("uncertain inode list is --\n"));
558 ino_rec
= findfirst_uncertain_inode_rec(agno
);
561 if (ino_rec
== NULL
) {
562 fprintf(stderr
, _("agno %d -- no inodes\n"), agno
);
566 printf(_("agno %d\n"), agno
);
568 while(ino_rec
!= NULL
) {
570 _("\tptr = %lx, start = 0x%x, free = 0x%llx, confirmed = 0x%llx\n"),
571 (unsigned long)ino_rec
,
572 ino_rec
->ino_startnum
,
573 (unsigned long long)ino_rec
->ir_free
,
574 (unsigned long long)ino_rec
->ino_confirmed
);
575 if (ino_rec
->ino_startnum
== 0)
577 ino_rec
= next_ino_rec(ino_rec
);
582 print_inode_list(xfs_agnumber_t agno
)
584 print_inode_list_int(agno
, 0);
588 print_uncertain_inode_list(xfs_agnumber_t agno
)
590 print_inode_list_int(agno
, 1);
594 * set parent -- use a bitmask and a packed array. The bitmask
595 * indicate which inodes have an entry in the array. An inode that
596 * is the Nth bit set in the mask is stored in the Nth location in
597 * the array where N starts at 0.
602 ino_tree_node_t
*irec
,
613 if (full_ino_ex_data
)
614 ptbl
= irec
->ino_un
.ex_data
->parents
;
616 ptbl
= irec
->ino_un
.plist
;
619 ptbl
= (parent_list_t
*)malloc(sizeof(parent_list_t
));
621 do_error(_("couldn't malloc parent list table\n"));
623 if (full_ino_ex_data
)
624 irec
->ino_un
.ex_data
->parents
= ptbl
;
626 irec
->ino_un
.plist
= ptbl
;
628 ptbl
->pmask
= 1LL << offset
;
629 ptbl
->pentries
= (xfs_ino_t
*)memalign(sizeof(xfs_ino_t
),
632 do_error(_("couldn't memalign pentries table\n"));
636 ptbl
->pentries
[0] = parent
;
641 if (ptbl
->pmask
& (1LL << offset
)) {
645 for (i
= 0; i
< offset
; i
++) {
646 if (ptbl
->pmask
& bitmask
)
651 ASSERT(target
< ptbl
->cnt
);
653 ptbl
->pentries
[target
] = parent
;
661 for (i
= 0; i
< XFS_INODES_PER_CHUNK
; i
++) {
662 if (ptbl
->pmask
& bitmask
) {
672 ASSERT(cnt
== ptbl
->cnt
);
674 ASSERT(cnt
>= target
);
676 tmp
= (xfs_ino_t
*)memalign(sizeof(xfs_ino_t
), (cnt
+ 1) * sizeof(xfs_ino_t
));
678 do_error(_("couldn't memalign pentries table\n"));
680 memmove(tmp
, ptbl
->pentries
, target
* sizeof(parent_entry_t
));
683 memmove(tmp
+ target
+ 1, ptbl
->pentries
+ target
,
684 (cnt
- target
) * sizeof(parent_entry_t
));
686 free(ptbl
->pentries
);
688 ptbl
->pentries
= tmp
;
693 ptbl
->pentries
[target
] = parent
;
694 ptbl
->pmask
|= (1LL << offset
);
698 get_inode_parent(ino_tree_node_t
*irec
, int offset
)
705 if (full_ino_ex_data
)
706 ptbl
= irec
->ino_un
.ex_data
->parents
;
708 ptbl
= irec
->ino_un
.plist
;
710 if (ptbl
->pmask
& (1LL << offset
)) {
714 for (i
= 0; i
< offset
; i
++) {
715 if (ptbl
->pmask
& bitmask
)
720 ASSERT(target
< ptbl
->cnt
);
722 return(ptbl
->pentries
[target
]);
729 alloc_ex_data(ino_tree_node_t
*irec
)
733 ptbl
= irec
->ino_un
.plist
;
734 irec
->ino_un
.ex_data
= (ino_ex_data_t
*)calloc(1, sizeof(ino_ex_data_t
));
735 if (irec
->ino_un
.ex_data
== NULL
)
736 do_error(_("could not malloc inode extra data\n"));
738 irec
->ino_un
.ex_data
->parents
= ptbl
;
740 switch (irec
->nlink_size
) {
741 case sizeof(__uint8_t
):
742 irec
->ino_un
.ex_data
->counted_nlinks
.un8
=
743 alloc_nlink_array(irec
->nlink_size
);
745 case sizeof(__uint16_t
):
746 irec
->ino_un
.ex_data
->counted_nlinks
.un16
=
747 alloc_nlink_array(irec
->nlink_size
);
749 case sizeof(__uint32_t
):
750 irec
->ino_un
.ex_data
->counted_nlinks
.un32
=
751 alloc_nlink_array(irec
->nlink_size
);
759 add_ino_ex_data(xfs_mount_t
*mp
)
761 ino_tree_node_t
*ino_rec
;
764 for (i
= 0; i
< mp
->m_sb
.sb_agcount
; i
++) {
765 ino_rec
= findfirst_inode_rec(i
);
767 while (ino_rec
!= NULL
) {
768 alloc_ex_data(ino_rec
);
769 ino_rec
= next_ino_rec(ino_rec
);
772 full_ino_ex_data
= 1;
776 avl_ino_start(avlnode_t
*node
)
778 return((uintptr_t) ((ino_tree_node_t
*) node
)->ino_startnum
);
782 avl_ino_end(avlnode_t
*node
)
785 ((ino_tree_node_t
*) node
)->ino_startnum
+
786 XFS_INODES_PER_CHUNK
));
789 avlops_t avl_ino_tree_ops
= {
795 incore_ino_init(xfs_mount_t
*mp
)
798 int agcount
= mp
->m_sb
.sb_agcount
;
800 if ((inode_tree_ptrs
= malloc(agcount
*
801 sizeof(avltree_desc_t
*))) == NULL
)
802 do_error(_("couldn't malloc inode tree descriptor table\n"));
803 if ((inode_uncertain_tree_ptrs
= malloc(agcount
*
804 sizeof(avltree_desc_t
*))) == NULL
)
806 _("couldn't malloc uncertain ino tree descriptor table\n"));
808 for (i
= 0; i
< agcount
; i
++) {
809 if ((inode_tree_ptrs
[i
] =
810 malloc(sizeof(avltree_desc_t
))) == NULL
)
811 do_error(_("couldn't malloc inode tree descriptor\n"));
812 if ((inode_uncertain_tree_ptrs
[i
] =
813 malloc(sizeof(avltree_desc_t
))) == NULL
)
815 _("couldn't malloc uncertain ino tree descriptor\n"));
817 for (i
= 0; i
< agcount
; i
++) {
818 avl_init_tree(inode_tree_ptrs
[i
], &avl_ino_tree_ops
);
819 avl_init_tree(inode_uncertain_tree_ptrs
[i
], &avl_ino_tree_ops
);
822 if ((last_rec
= malloc(sizeof(ino_tree_node_t
*) * agcount
)) == NULL
)
823 do_error(_("couldn't malloc uncertain inode cache area\n"));
825 memset(last_rec
, 0, sizeof(ino_tree_node_t
*) * agcount
);
827 full_ino_ex_data
= 0;