]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - repair/incore.h
xfs_repair: check and repair quota metadata
[thirdparty/xfsprogs-dev.git] / repair / incore.h
CommitLineData
2bd0ea18 1/*
da23017d
NS
2 * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
3 * All Rights Reserved.
dfc130f3 4 *
da23017d
NS
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
2bd0ea18 7 * published by the Free Software Foundation.
dfc130f3 8 *
da23017d
NS
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.
dfc130f3 13 *
da23017d
NS
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
2bd0ea18
NS
17 */
18
2556c98b
BN
19#ifndef XFS_REPAIR_INCORE_H
20#define XFS_REPAIR_INCORE_H
21
22#include "avl.h"
79872d6e
BN
23
24
2bd0ea18
NS
25/*
26 * contains definition information. implementation (code)
27 * is spread out in separate files.
28 */
29
2bd0ea18 30/*
8961bfde 31 * block map -- track state of each filesystem block.
2bd0ea18 32 */
2bd0ea18 33
8961bfde
BN
34void init_bmaps(xfs_mount_t *mp);
35void reset_bmaps(xfs_mount_t *mp);
36void free_bmaps(xfs_mount_t *mp);
37
38void set_bmap_ext(xfs_agnumber_t agno, xfs_agblock_t agbno,
39 xfs_extlen_t blen, int state);
40int get_bmap_ext(xfs_agnumber_t agno, xfs_agblock_t agbno,
41 xfs_agblock_t maxbno, xfs_extlen_t *blen);
42
5a35bf2c
DC
43void set_rtbmap(xfs_rtblock_t bno, int state);
44int get_rtbmap(xfs_rtblock_t bno);
8961bfde
BN
45
46static inline void
47set_bmap(xfs_agnumber_t agno, xfs_agblock_t agbno, int state)
48{
49 set_bmap_ext(agno, agbno, 1, state);
50}
51
52static inline int
53get_bmap(xfs_agnumber_t agno, xfs_agblock_t agbno)
54{
55 return get_bmap_ext(agno, agbno, agbno + 1, NULL);
56}
2bd0ea18
NS
57
58/*
59 * extent tree definitions
60 * right now, there are 3 trees per AG, a bno tree, a bcnt tree
61 * and a tree for dup extents. If the code is modified in the
62 * future to use an extent tree instead of a bitmask for tracking
63 * fs blocks, then we could lose the dup extent tree if we labelled
64 * each extent with the inode that owned it.
65 */
66
67typedef unsigned char extent_state_t;
68
69typedef struct extent_tree_node {
70 avlnode_t avl_node;
71 xfs_agblock_t ex_startblock; /* starting block (agbno) */
72 xfs_extlen_t ex_blockcount; /* number of blocks in extent */
73 extent_state_t ex_state; /* see state flags below */
74
75 struct extent_tree_node *next; /* for bcnt extent lists */
b87887d4 76 struct extent_tree_node *last; /* for bcnt extent list anchors */
2bd0ea18
NS
77#if 0
78 xfs_ino_t ex_inode; /* owner, NULL if free or */
79 /* multiply allocated */
80#endif
81} extent_tree_node_t;
82
83typedef struct rt_extent_tree_node {
84 avlnode_t avl_node;
5a35bf2c 85 xfs_rtblock_t rt_startblock; /* starting realtime block */
2bd0ea18
NS
86 xfs_extlen_t rt_blockcount; /* number of blocks in extent */
87 extent_state_t rt_state; /* see state flags below */
88
89#if 0
90 xfs_ino_t ex_inode; /* owner, NULL if free or */
91 /* multiply allocated */
92#endif
93} rt_extent_tree_node_t;
94
95/* extent states, prefix with XR_ to avoid conflict with buffer cache defines */
96
97#define XR_E_UNKNOWN 0 /* unknown state */
98#define XR_E_FREE1 1 /* free block (marked by one fs space tree) */
99#define XR_E_FREE 2 /* free block (marked by both fs space trees) */
100#define XR_E_INUSE 3 /* extent used by file/dir data or metadata */
101#define XR_E_INUSE_FS 4 /* extent used by fs ag header or log */
102#define XR_E_MULT 5 /* extent is multiply referenced */
103#define XR_E_INO 6 /* extent used by inodes (inode blocks) */
104#define XR_E_FS_MAP 7 /* extent used by fs space/inode maps */
0f94fa4b
DW
105#define XR_E_INUSE1 8 /* used block (marked by rmap btree) */
106#define XR_E_INUSE_FS1 9 /* used by fs ag header or log (rmap btree) */
107#define XR_E_INO1 10 /* used by inodes (marked by rmap btree) */
108#define XR_E_FS_MAP1 11 /* used by fs space/inode maps (rmap btree) */
18c44aa9 109#define XR_E_REFC 12 /* used by fs ag reference count btree */
13ef9674
DW
110#define XR_E_COW 13 /* leftover cow extent */
111#define XR_E_BAD_STATE 14
1e77098c 112
2bd0ea18
NS
113/* separate state bit, OR'ed into high (4th) bit of ex_state field */
114
115#define XR_E_WRITTEN 0x8 /* extent has been written out, can't reclaim */
116#define good_state(state) (((state) & (~XR_E_WRITTEN)) >= XR_E_UNKNOWN && \
117 ((state) & (~XR_E_WRITTEN) < XF_E_BAD_STATE))
118#define written(state) ((state) & XR_E_WRITTEN)
119#define set_written(state) (state) &= XR_E_WRITTEN
120
121/*
122 * bno extent tree functions
123 */
124void
125add_bno_extent(xfs_agnumber_t agno, xfs_agblock_t startblock,
126 xfs_extlen_t blockcount);
127
128extent_tree_node_t *
129findfirst_bno_extent(xfs_agnumber_t agno);
130
131extent_tree_node_t *
132find_bno_extent(xfs_agnumber_t agno, xfs_agblock_t agbno);
133
134extent_tree_node_t *
135findfirst_bno_extent(xfs_agnumber_t agno);
136
137#define findnext_bno_extent(exent_ptr) \
138 ((extent_tree_node_t *) ((exent_ptr)->avl_node.avl_nextino))
139
140void
141get_bno_extent(xfs_agnumber_t agno, extent_tree_node_t *ext);
142
143/*
144 * bcnt tree functions
145 */
146void
147add_bcnt_extent(xfs_agnumber_t agno, xfs_agblock_t startblock,
148 xfs_extlen_t blockcount);
149
150extent_tree_node_t *
151findfirst_bcnt_extent(xfs_agnumber_t agno);
152
153extent_tree_node_t *
154find_bcnt_extent(xfs_agnumber_t agno, xfs_agblock_t agbno);
155
156extent_tree_node_t *
157findbiggest_bcnt_extent(xfs_agnumber_t agno);
158
159extent_tree_node_t *
160findnext_bcnt_extent(xfs_agnumber_t agno, extent_tree_node_t *ext);
161
162extent_tree_node_t *
163get_bcnt_extent(xfs_agnumber_t agno, xfs_agblock_t startblock,
164 xfs_extlen_t blockcount);
165
166/*
167 * duplicate extent tree functions
168 */
2bd0ea18 169
79872d6e
BN
170int add_dup_extent(xfs_agnumber_t agno, xfs_agblock_t startblock,
171 xfs_extlen_t blockcount);
172int search_dup_extent(xfs_agnumber_t agno,
173 xfs_agblock_t start_agbno, xfs_agblock_t end_agbno);
5a35bf2c 174void add_rt_dup_extent(xfs_rtblock_t startblock,
2bd0ea18
NS
175 xfs_extlen_t blockcount);
176
177int search_rt_dup_extent(xfs_mount_t *mp,
5a35bf2c 178 xfs_rtblock_t bno);
2bd0ea18
NS
179
180/*
181 * extent/tree recyling and deletion routines
182 */
183
184/*
185 * return an extent node to the extent node free list
186 */
187void release_extent_tree_node(extent_tree_node_t *node);
188
189/*
190 * recycle all the nodes in the per-AG tree
191 */
192void release_dup_extent_tree(xfs_agnumber_t agno);
193void release_agbno_extent_tree(xfs_agnumber_t agno);
194void release_agbcnt_extent_tree(xfs_agnumber_t agno);
195
196/*
197 * realtime duplicate extent tree - this one actually frees the memory
198 */
199void free_rt_dup_extent_tree(xfs_mount_t *mp);
200
c1f7a46c 201void incore_ext_init(xfs_mount_t *);
2bd0ea18
NS
202/*
203 * per-AG extent trees shutdown routine -- all (bno, bcnt and dup)
204 * at once. this one actually frees the memory instead of just recyling
205 * the nodes.
206 */
207void incore_ext_teardown(xfs_mount_t *mp);
c1f7a46c
BN
208void incore_ino_init(xfs_mount_t *);
209
52cb19dc
CH
210int count_bno_extents(xfs_agnumber_t);
211int count_bno_extents_blocks(xfs_agnumber_t, uint *);
212int count_bcnt_extents(xfs_agnumber_t);
213
2bd0ea18
NS
214/*
215 * inode definitions
216 */
217
218/* inode types */
219
220#define XR_INO_UNKNOWN 0 /* unknown */
221#define XR_INO_DIR 1 /* directory */
222#define XR_INO_RTDATA 2 /* realtime file */
223#define XR_INO_RTBITMAP 3 /* realtime bitmap inode */
224#define XR_INO_RTSUM 4 /* realtime summary inode */
225#define XR_INO_DATA 5 /* regular file */
226#define XR_INO_SYMLINK 6 /* symlink */
227#define XR_INO_CHRDEV 7 /* character device */
228#define XR_INO_BLKDEV 8 /* block device */
229#define XR_INO_SOCK 9 /* socket */
230#define XR_INO_FIFO 10 /* fifo */
231#define XR_INO_MOUNTPOINT 11 /* mountpoint */
5857dce9
ES
232#define XR_INO_UQUOTA 12 /* user quota inode */
233#define XR_INO_GQUOTA 13 /* group quota inode */
234#define XR_INO_PQUOTA 14 /* project quota inode */
2bd0ea18
NS
235
236/* inode allocation tree */
237
238/*
239 * Inodes in the inode allocation trees are allocated in chunks.
240 * Those groups can be easily duplicated in our trees.
241 * Disconnected inodes are harder. We can do one of two
242 * things in that case: if we know the inode allocation btrees
243 * are good, then we can disallow directory references to unknown
244 * inode chunks. If the inode allocation trees have been trashed or
245 * we feel like being aggressive, then as we hit unknown inodes,
246 * we can search on the disk for all contiguous inodes and see if
247 * they fit into chunks. Before putting them into the inode tree,
248 * we can scan each inode starting at the earliest inode to see which
249 * ones are good. This protects us from the pathalogical case of
250 * inodes appearing in user-data. We still may have to mark the
251 * inodes as "possibly fake" so that if a file claims the blocks,
252 * we decide to believe the inodes, especially if they're not
253 * connected.
254 */
255
256#define PLIST_CHUNK_SIZE 4
257
258typedef xfs_ino_t parent_entry_t;
259
0f012a4c
BN
260struct nlink_ops;
261
2bd0ea18 262typedef struct parent_list {
14f8b681 263 uint64_t pmask;
2bd0ea18
NS
264 parent_entry_t *pentries;
265#ifdef DEBUG
266 short cnt;
267#endif
268} parent_list_t;
269
edfb350c 270union ino_nlink {
14f8b681
DW
271 uint8_t *un8;
272 uint16_t *un16;
273 uint32_t *un32;
edfb350c
CH
274};
275
0f012a4c 276typedef struct ino_ex_data {
14f8b681
DW
277 uint64_t ino_reached; /* bit == 1 if reached */
278 uint64_t ino_processed; /* reference checked bit mask */
2bd0ea18 279 parent_list_t *parents;
edfb350c 280 union ino_nlink counted_nlinks;/* counted nlinks in P6 */
0f012a4c 281} ino_ex_data_t;
2bd0ea18
NS
282
283typedef struct ino_tree_node {
284 avlnode_t avl_node;
285 xfs_agino_t ino_startnum; /* starting inode # */
286 xfs_inofree_t ir_free; /* inode free bit mask */
14f8b681
DW
287 uint64_t ir_sparse; /* sparse inode bitmask */
288 uint64_t ino_confirmed; /* confirmed bitmask */
289 uint64_t ino_isa_dir; /* bit == 1 if a directory */
290 uint64_t ino_was_rl; /* bit == 1 if reflink flag set */
291 uint64_t ino_is_rl; /* bit == 1 if reflink flag should be set */
292 uint8_t nlink_size;
edfb350c 293 union ino_nlink disk_nlinks; /* on-disk nlinks, set in P3 */
2bd0ea18 294 union {
0f012a4c
BN
295 ino_ex_data_t *ex_data; /* phases 6,7 */
296 parent_list_t *plist; /* phases 2-5 */
2bd0ea18 297 } ino_un;
14f8b681 298 uint8_t *ftypes; /* phases 3,6 */
2bd0ea18
NS
299} ino_tree_node_t;
300
14f8b681
DW
301#define INOS_PER_IREC (sizeof(uint64_t) * NBBY)
302#define IREC_MASK(i) ((uint64_t)1 << (i))
f4ef1178 303
0f012a4c 304void add_ino_ex_data(xfs_mount_t *mp);
2bd0ea18
NS
305
306/*
307 * return an inode record to the free inode record pool
308 */
309void free_inode_rec(xfs_agnumber_t agno, ino_tree_node_t *ino_rec);
310
311/*
312 * get pulls the inode record from the good inode tree
313 */
1ae311d5
LC
314void get_inode_rec(struct xfs_mount *mp, xfs_agnumber_t agno,
315 ino_tree_node_t *ino_rec);
2bd0ea18 316
1e77098c 317extern avltree_desc_t **inode_tree_ptrs;
1b9f3650
CM
318
319static inline int
320get_inode_offset(struct xfs_mount *mp, xfs_ino_t ino, ino_tree_node_t *irec)
321{
322 return XFS_INO_TO_AGINO(mp, ino) - irec->ino_startnum;
323}
78a0dc91 324static inline ino_tree_node_t *
1e77098c
MV
325findfirst_inode_rec(xfs_agnumber_t agno)
326{
327 return((ino_tree_node_t *) inode_tree_ptrs[agno]->avl_firstino);
328}
78a0dc91 329static inline ino_tree_node_t *
1ae311d5 330find_inode_rec(struct xfs_mount *mp, xfs_agnumber_t agno, xfs_agino_t ino)
1e77098c 331{
1ae311d5
LC
332 /*
333 * Is the AG inside the file system
334 */
335 if (agno >= mp->m_sb.sb_agcount)
336 return NULL;
1e77098c
MV
337 return((ino_tree_node_t *)
338 avl_findrange(inode_tree_ptrs[agno], ino));
339}
1ae311d5 340void find_inode_rec_range(struct xfs_mount *mp, xfs_agnumber_t agno,
2bd0ea18
NS
341 xfs_agino_t start_ino, xfs_agino_t end_ino,
342 ino_tree_node_t **first, ino_tree_node_t **last);
343
344/*
345 * set inode states -- setting an inode to used or free also
346 * automatically marks it as "existing". Note -- all the inode
347 * add/set/get routines assume a valid inode number.
348 */
1ae311d5
LC
349ino_tree_node_t *set_inode_used_alloc(struct xfs_mount *mp, xfs_agnumber_t agno,
350 xfs_agino_t ino);
351ino_tree_node_t *set_inode_free_alloc(struct xfs_mount *mp, xfs_agnumber_t agno,
352 xfs_agino_t ino);
2bd0ea18
NS
353
354void print_inode_list(xfs_agnumber_t agno);
355void print_uncertain_inode_list(xfs_agnumber_t agno);
356
357/*
358 * separate trees for uncertain inodes (they may not exist).
359 */
360ino_tree_node_t *findfirst_uncertain_inode_rec(xfs_agnumber_t agno);
2d9475a4
NS
361ino_tree_node_t *find_uncertain_inode_rec(xfs_agnumber_t agno,
362 xfs_agino_t ino);
2bd0ea18
NS
363void add_inode_uncertain(xfs_mount_t *mp,
364 xfs_ino_t ino, int free);
aaca101b
DC
365void add_aginode_uncertain(struct xfs_mount *mp,
366 xfs_agnumber_t agno,
2bd0ea18 367 xfs_agino_t agino, int free);
1ae311d5
LC
368void get_uncertain_inode_rec(struct xfs_mount *mp,
369 xfs_agnumber_t agno,
2bd0ea18
NS
370 ino_tree_node_t *ino_rec);
371void clear_uncertain_ino_cache(xfs_agnumber_t agno);
372
373/*
374 * return next in-order inode tree node. takes an "ino_tree_node_t *"
375 */
376#define next_ino_rec(ino_node_ptr) \
377 ((ino_tree_node_t *) ((ino_node_ptr)->avl_node.avl_nextino))
378/*
379 * return the next linked inode (forward avl tree link)-- meant to be used
380 * by linked list routines (uncertain inode routines/records)
381 */
382#define next_link_rec(ino_node_ptr) \
383 ((ino_tree_node_t *) ((ino_node_ptr)->avl_node.avl_forw))
384
01159bd2
BF
385/*
386 * finobt helpers
387 */
c77c41ee
BF
388
389static inline bool
390inode_rec_has_free(struct ino_tree_node *ino_rec)
391{
392 /* must have real, allocated inodes for finobt */
393 return ino_rec->ir_free & ~ino_rec->ir_sparse;
394}
395
01159bd2
BF
396static inline ino_tree_node_t *
397findfirst_free_inode_rec(xfs_agnumber_t agno)
398{
399 ino_tree_node_t *ino_rec;
400
401 ino_rec = findfirst_inode_rec(agno);
402
c77c41ee 403 while (ino_rec && !inode_rec_has_free(ino_rec))
01159bd2
BF
404 ino_rec = next_ino_rec(ino_rec);
405
406 return ino_rec;
407}
408
409static inline ino_tree_node_t *
410next_free_ino_rec(ino_tree_node_t *ino_rec)
411{
412 ino_rec = next_ino_rec(ino_rec);
413
c77c41ee 414 while (ino_rec && !inode_rec_has_free(ino_rec))
01159bd2
BF
415 ino_rec = next_ino_rec(ino_rec);
416
417 return ino_rec;
418}
419
2bd0ea18 420/*
f4ef1178
CH
421 * Has an inode been processed for phase 6 (reference count checking)?
422 *
423 * add_inode_refchecked() is set on an inode when it gets traversed
424 * during the reference count phase (6). It's set so that if the inode
425 * is a directory, it's traversed (and it's links counted) only once.
2bd0ea18 426 */
f4ef1178
CH
427static inline void add_inode_refchecked(struct ino_tree_node *irec, int offset)
428{
429 irec->ino_un.ex_data->ino_processed |= IREC_MASK(offset);
430}
2bd0ea18 431
f4ef1178
CH
432static inline int is_inode_refchecked(struct ino_tree_node *irec, int offset)
433{
434 return (irec->ino_un.ex_data->ino_processed & IREC_MASK(offset)) != 0;
435}
2bd0ea18
NS
436
437/*
f4ef1178 438 * set/test is inode known to be valid (although perhaps corrupt)
2bd0ea18 439 */
f4ef1178
CH
440static inline void set_inode_confirmed(struct ino_tree_node *irec, int offset)
441{
442 irec->ino_confirmed |= IREC_MASK(offset);
443}
2bd0ea18 444
f4ef1178
CH
445static inline int is_inode_confirmed(struct ino_tree_node *irec, int offset)
446{
447 return (irec->ino_confirmed & IREC_MASK(offset)) != 0;
448}
2bd0ea18
NS
449
450/*
f4ef1178 451 * set/clear/test is inode a directory inode
2bd0ea18 452 */
f4ef1178
CH
453static inline void set_inode_isadir(struct ino_tree_node *irec, int offset)
454{
455 irec->ino_isa_dir |= IREC_MASK(offset);
456}
2bd0ea18 457
f4ef1178
CH
458static inline void clear_inode_isadir(struct ino_tree_node *irec, int offset)
459{
460 irec->ino_isa_dir &= ~IREC_MASK(offset);
461}
2bd0ea18 462
f4ef1178
CH
463static inline int inode_isadir(struct ino_tree_node *irec, int offset)
464{
465 return (irec->ino_isa_dir & IREC_MASK(offset)) != 0;
466}
2bd0ea18
NS
467
468/*
469 * set/clear/test is inode free or used
470 */
f4ef1178
CH
471static inline void set_inode_free(struct ino_tree_node *irec, int offset)
472{
473 set_inode_confirmed(irec, offset);
474 irec->ir_free |= XFS_INOBT_MASK(offset);
2bd0ea18 475
f4ef1178 476}
56b2de80 477
f4ef1178
CH
478static inline void set_inode_used(struct ino_tree_node *irec, int offset)
479{
480 set_inode_confirmed(irec, offset);
481 irec->ir_free &= ~XFS_INOBT_MASK(offset);
482}
2bd0ea18 483
f4ef1178
CH
484static inline int is_inode_free(struct ino_tree_node *irec, int offset)
485{
486 return (irec->ir_free & XFS_INOBT_MASK(offset)) != 0;
487}
2bd0ea18 488
c749bd55
BF
489/*
490 * set/test is inode sparse (not physically allocated)
491 */
492static inline void set_inode_sparse(struct ino_tree_node *irec, int offset)
493{
494 irec->ir_sparse |= XFS_INOBT_MASK(offset);
495}
496
497static inline bool is_inode_sparse(struct ino_tree_node *irec, int offset)
498{
499 return irec->ir_sparse & XFS_INOBT_MASK(offset);
500}
501
7e174ec7
DW
502/*
503 * set/clear/test was inode marked as reflinked
504 */
505static inline void set_inode_was_rl(struct ino_tree_node *irec, int offset)
506{
507 irec->ino_was_rl |= IREC_MASK(offset);
508}
509
510static inline void clear_inode_was_rl(struct ino_tree_node *irec, int offset)
511{
512 irec->ino_was_rl &= ~IREC_MASK(offset);
513}
514
515static inline int inode_was_rl(struct ino_tree_node *irec, int offset)
516{
517 return (irec->ino_was_rl & IREC_MASK(offset)) != 0;
518}
519
520/*
521 * set/clear/test should inode be marked as reflinked
522 */
523static inline void set_inode_is_rl(struct ino_tree_node *irec, int offset)
524{
525 irec->ino_is_rl |= IREC_MASK(offset);
526}
527
528static inline void clear_inode_is_rl(struct ino_tree_node *irec, int offset)
529{
530 irec->ino_is_rl &= ~IREC_MASK(offset);
531}
532
533static inline int inode_is_rl(struct ino_tree_node *irec, int offset)
534{
535 return (irec->ino_is_rl & IREC_MASK(offset)) != 0;
536}
537
2bd0ea18
NS
538/*
539 * add_inode_reached() is set on inode I only if I has been reached
540 * by an inode P claiming to be the parent and if I is a directory,
541 * the .. link in the I says that P is I's parent.
542 *
543 * add_inode_ref() is called every time a link to an inode is
544 * detected and drop_inode_ref() is called every time a link to
545 * an inode that we've counted is removed.
546 */
edfb350c
CH
547void add_inode_ref(struct ino_tree_node *irec, int offset);
548void drop_inode_ref(struct ino_tree_node *irec, int offset);
14f8b681 549uint32_t num_inode_references(struct ino_tree_node *irec, int offset);
2bd0ea18 550
14f8b681
DW
551void set_inode_disk_nlinks(struct ino_tree_node *irec, int offset, uint32_t nlinks);
552uint32_t get_inode_disk_nlinks(struct ino_tree_node *irec, int offset);
1e77098c 553
f4ef1178 554static inline int is_inode_reached(struct ino_tree_node *irec, int offset)
1e77098c 555{
f4ef1178
CH
556 ASSERT(irec->ino_un.ex_data != NULL);
557 return (irec->ino_un.ex_data->ino_reached & IREC_MASK(offset)) != 0;
1e77098c
MV
558}
559
f4ef1178 560static inline void add_inode_reached(struct ino_tree_node *irec, int offset)
1e77098c 561{
f4ef1178
CH
562 add_inode_ref(irec, offset);
563 irec->ino_un.ex_data->ino_reached |= IREC_MASK(offset);
0f012a4c
BN
564}
565
aaca101b
DC
566/*
567 * get/set inode filetype. Only used if the superblock feature bit is set
568 * which allocates irec->ftypes.
569 */
570static inline void
571set_inode_ftype(struct ino_tree_node *irec,
572 int ino_offset,
14f8b681 573 uint8_t ftype)
aaca101b
DC
574{
575 if (irec->ftypes)
576 irec->ftypes[ino_offset] = ftype;
577}
578
14f8b681 579static inline uint8_t
aaca101b
DC
580get_inode_ftype(
581 struct ino_tree_node *irec,
582 int ino_offset)
583{
584 if (!irec->ftypes)
585 return XFS_DIR3_FT_UNKNOWN;
586 return irec->ftypes[ino_offset];
587}
588
2bd0ea18
NS
589/*
590 * set/get inode number of parent -- works for directory inodes only
591 */
592void set_inode_parent(ino_tree_node_t *irec, int ino_offset,
593 xfs_ino_t ino);
2bd0ea18
NS
594xfs_ino_t get_inode_parent(ino_tree_node_t *irec, int ino_offset);
595
2e162270
ES
596/*
597 * Allocate extra inode data
598 */
599void alloc_ex_data(ino_tree_node_t *irec);
600
2bd0ea18
NS
601/*
602 * bmap cursor for tracking and fixing bmap btrees. All xfs btrees number
603 * the levels with 0 being the leaf and every level up being 1 greater.
604 */
605
606#define XR_MAX_BMLEVELS 10 /* XXX - rcc need to verify number */
607
608typedef struct bm_level_state {
5a35bf2c
DC
609 xfs_fsblock_t fsbno;
610 xfs_fsblock_t left_fsbno;
611 xfs_fsblock_t right_fsbno;
14f8b681
DW
612 uint64_t first_key;
613 uint64_t last_key;
2bd0ea18
NS
614/*
615 int level;
14f8b681 616 uint64_t prev_last_key;
2bd0ea18
NS
617 xfs_buf_t *bp;
618 xfs_bmbt_block_t *block;
619*/
620} bm_level_state_t;
621
622typedef struct bm_cursor {
623 int num_levels;
624 xfs_ino_t ino;
625 xfs_dinode_t *dip;
626 bm_level_state_t level[XR_MAX_BMLEVELS];
627} bmap_cursor_t;
628
629void init_bm_cursor(bmap_cursor_t *cursor, int num_level);
2556c98b 630
ac9a3f73
BF
631/*
632 * On-disk inobt record helpers. The sparse inode record format has a single
633 * byte freecount. The older format has a 32-bit freecount and thus byte
634 * conversion is necessary.
635 */
636
637static inline int
638inorec_get_freecount(
639 struct xfs_mount *mp,
640 struct xfs_inobt_rec *rp)
641{
642 if (xfs_sb_version_hassparseinodes(&mp->m_sb))
643 return rp->ir_u.sp.ir_freecount;
644 return be32_to_cpu(rp->ir_u.f.ir_freecount);
645}
646
647static inline void
648inorec_set_freecount(
649 struct xfs_mount *mp,
650 struct xfs_inobt_rec *rp,
651 int freecount)
652{
653 if (xfs_sb_version_hassparseinodes(&mp->m_sb))
654 rp->ir_u.sp.ir_freecount = freecount;
655 else
656 rp->ir_u.f.ir_freecount = cpu_to_be32(freecount);
657}
658
2556c98b 659#endif /* XFS_REPAIR_INCORE_H */