2 * Copyright (c) 2000-2002 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/
46 DBM_UNKNOWN
, DBM_AGF
, DBM_AGFL
, DBM_AGI
,
47 DBM_ATTR
, DBM_BTBMAPA
, DBM_BTBMAPD
, DBM_BTBNO
,
48 DBM_BTCNT
, DBM_BTINO
, DBM_DATA
, DBM_DIR
,
49 DBM_FREE1
, DBM_FREE2
, DBM_FREELIST
, DBM_INODE
,
50 DBM_LOG
, DBM_MISSING
, DBM_QUOTA
, DBM_RTBITMAP
,
51 DBM_RTDATA
, DBM_RTFREE
, DBM_RTSUM
, DBM_SB
,
56 typedef struct inodata
{
64 struct inodata
*parent
;
67 #define MIN_INODATA_HASH_SIZE 256
68 #define MAX_INODATA_HASH_SIZE 65536
69 #define INODATA_AVG_HASH_LENGTH 8
71 typedef struct qinfo
{
77 #define QDATA_HASH_SIZE 256
78 typedef struct qdata
{
85 typedef struct blkent
{
86 xfs_fileoff_t startoff
;
88 xfs_fsblock_t blks
[1];
90 #define BLKENT_SIZE(n) \
91 (offsetof(blkent_t, blks) + (sizeof(xfs_fsblock_t) * (n)))
93 typedef struct blkmap
{
98 #define BLKMAP_SIZE(n) \
99 (offsetof(blkmap_t, ents) + (sizeof(blkent_t *) * (n)))
101 typedef struct freetab
{
104 xfs_dir2_data_off_t ents
[1];
106 #define FREETAB_SIZE(n) \
107 (offsetof(freetab_t, ents) + (sizeof(xfs_dir2_data_off_t) * (n)))
109 typedef struct dirhash
{
110 struct dirhash
*next
;
111 xfs_dir2_leaf_entry_t entry
;
114 #define DIR_HASH_SIZE 1024
115 #define DIR_HASH_FUNC(h,a) (((h) ^ (a)) % DIR_HASH_SIZE)
117 static xfs_extlen_t agffreeblks
;
118 static xfs_extlen_t agflongest
;
119 static xfs_agino_t agicount
;
120 static xfs_agino_t agifreecount
;
121 static xfs_fsblock_t
*blist
;
122 static int blist_size
;
123 static char **dbmap
; /* really dbm_t:8 */
124 static dirhash_t
**dirhash
;
126 static __uint64_t fdblocks
;
127 static __uint64_t frextents
;
128 static __uint64_t icount
;
129 static __uint64_t ifree
;
130 static inodata_t
***inodata
;
131 static int inodata_hash_size
;
132 static inodata_t
***inomap
;
135 static qdata_t
**qgdata
;
137 static qdata_t
**qudata
;
139 static unsigned sbversion
;
140 static int sbver_err
;
141 static int serious_error
;
143 static xfs_suminfo_t
*sumcompute
;
144 static xfs_suminfo_t
*sumfile
;
145 static const char *typename
[] = {
175 #define CHECK_BLIST(b) (blist_size && check_blist(b))
176 #define CHECK_BLISTA(a,b) \
177 (blist_size && check_blist(XFS_AGB_TO_FSB(mp, a, b)))
179 typedef void (*scan_lbtree_f_t
)(xfs_btree_lblock_t
*block
,
191 typedef void (*scan_sbtree_f_t
)(xfs_btree_sblock_t
*block
,
197 static void add_blist(xfs_fsblock_t bno
);
198 static void add_ilist(xfs_ino_t ino
);
199 static void addlink_inode(inodata_t
*id
);
200 static void addname_inode(inodata_t
*id
, char *name
, int namelen
);
201 static void addparent_inode(inodata_t
*id
, xfs_ino_t parent
);
202 static void blkent_append(blkent_t
**entp
, xfs_fsblock_t b
,
204 static blkent_t
*blkent_new(xfs_fileoff_t o
, xfs_fsblock_t b
,
206 static void blkent_prepend(blkent_t
**entp
, xfs_fsblock_t b
,
208 static blkmap_t
*blkmap_alloc(xfs_extnum_t
);
209 static void blkmap_free(blkmap_t
*blkmap
);
210 static xfs_fsblock_t
blkmap_get(blkmap_t
*blkmap
, xfs_fileoff_t o
);
211 static int blkmap_getn(blkmap_t
*blkmap
, xfs_fileoff_t o
, int nb
,
213 static void blkmap_grow(blkmap_t
**blkmapp
, blkent_t
**entp
,
215 static xfs_fileoff_t
blkmap_next_off(blkmap_t
*blkmap
, xfs_fileoff_t o
,
217 static void blkmap_set_blk(blkmap_t
**blkmapp
, xfs_fileoff_t o
,
219 static void blkmap_set_ext(blkmap_t
**blkmapp
, xfs_fileoff_t o
,
220 xfs_fsblock_t b
, xfs_extlen_t c
);
221 static void blkmap_shrink(blkmap_t
*blkmap
, blkent_t
**entp
);
222 static int blockfree_f(int argc
, char **argv
);
223 static int blockget_f(int argc
, char **argv
);
225 static int blocktrash_f(int argc
, char **argv
);
227 static int blockuse_f(int argc
, char **argv
);
228 static int check_blist(xfs_fsblock_t bno
);
229 static void check_dbmap(xfs_agnumber_t agno
, xfs_agblock_t agbno
,
230 xfs_extlen_t len
, dbm_t type
);
231 static int check_inomap(xfs_agnumber_t agno
, xfs_agblock_t agbno
,
232 xfs_extlen_t len
, xfs_ino_t c_ino
);
233 static void check_linkcounts(xfs_agnumber_t agno
);
234 static int check_range(xfs_agnumber_t agno
, xfs_agblock_t agbno
,
236 static void check_rdbmap(xfs_drfsbno_t bno
, xfs_extlen_t len
,
238 static int check_rinomap(xfs_drfsbno_t bno
, xfs_extlen_t len
,
240 static void check_rootdir(void);
241 static int check_rrange(xfs_drfsbno_t bno
, xfs_extlen_t len
);
242 static void check_set_dbmap(xfs_agnumber_t agno
,
243 xfs_agblock_t agbno
, xfs_extlen_t len
,
244 dbm_t type1
, dbm_t type2
,
245 xfs_agnumber_t c_agno
,
246 xfs_agblock_t c_agbno
);
247 static void check_set_rdbmap(xfs_drfsbno_t bno
, xfs_extlen_t len
,
248 dbm_t type1
, dbm_t type2
);
249 static void check_summary(void);
250 static void checknot_dbmap(xfs_agnumber_t agno
, xfs_agblock_t agbno
,
251 xfs_extlen_t len
, int typemask
);
252 static void checknot_rdbmap(xfs_drfsbno_t bno
, xfs_extlen_t len
,
254 static void dir_hash_add(xfs_dahash_t hash
,
255 xfs_dir2_dataptr_t addr
);
256 static void dir_hash_check(inodata_t
*id
, int v
);
257 static void dir_hash_done(void);
258 static void dir_hash_init(void);
259 static int dir_hash_see(xfs_dahash_t hash
,
260 xfs_dir2_dataptr_t addr
);
261 static inodata_t
*find_inode(xfs_ino_t ino
, int add
);
262 static void free_inodata(xfs_agnumber_t agno
);
263 static int init(int argc
, char **argv
);
264 static char *inode_name(xfs_ino_t ino
, inodata_t
**ipp
);
265 static int ncheck_f(int argc
, char **argv
);
266 static char *prepend_path(char *oldpath
, char *parent
);
267 static xfs_ino_t
process_block_dir_v2(blkmap_t
*blkmap
, int *dot
,
268 int *dotdot
, inodata_t
*id
);
269 static void process_bmbt_reclist(xfs_bmbt_rec_32_t
*rp
, int numrecs
,
270 dbm_t type
, inodata_t
*id
,
273 static void process_btinode(inodata_t
*id
, xfs_dinode_t
*dip
,
274 dbm_t type
, xfs_drfsbno_t
*totd
,
275 xfs_drfsbno_t
*toti
, xfs_extnum_t
*nex
,
276 blkmap_t
**blkmapp
, int whichfork
);
277 static xfs_ino_t
process_data_dir_v2(int *dot
, int *dotdot
,
278 inodata_t
*id
, int v
,
280 freetab_t
**freetabp
);
281 static xfs_dir2_data_free_t
282 *process_data_dir_v2_freefind(xfs_dir2_data_t
*data
,
283 xfs_dir2_data_unused_t
*dup
);
284 static void process_dir(xfs_dinode_t
*dip
, blkmap_t
*blkmap
,
286 static int process_dir_v1(xfs_dinode_t
*dip
, blkmap_t
*blkmap
,
287 int *dot
, int *dotdot
, inodata_t
*id
,
289 static int process_dir_v2(xfs_dinode_t
*dip
, blkmap_t
*blkmap
,
290 int *dot
, int *dotdot
, inodata_t
*id
,
292 static void process_exinode(inodata_t
*id
, xfs_dinode_t
*dip
,
293 dbm_t type
, xfs_drfsbno_t
*totd
,
294 xfs_drfsbno_t
*toti
, xfs_extnum_t
*nex
,
295 blkmap_t
**blkmapp
, int whichfork
);
296 static void process_inode(xfs_agf_t
*agf
, xfs_agino_t agino
,
297 xfs_dinode_t
*dip
, int isfree
);
298 static void process_lclinode(inodata_t
*id
, xfs_dinode_t
*dip
,
299 dbm_t type
, xfs_drfsbno_t
*totd
,
300 xfs_drfsbno_t
*toti
, xfs_extnum_t
*nex
,
301 blkmap_t
**blkmapp
, int whichfork
);
302 static xfs_ino_t
process_leaf_dir_v1(blkmap_t
*blkmap
, int *dot
,
303 int *dotdot
, inodata_t
*id
);
304 static xfs_ino_t
process_leaf_dir_v1_int(int *dot
, int *dotdot
,
306 static xfs_ino_t
process_leaf_node_dir_v2(blkmap_t
*blkmap
, int *dot
,
307 int *dotdot
, inodata_t
*id
,
308 xfs_fsize_t dirsize
);
309 static void process_leaf_node_dir_v2_free(inodata_t
*id
, int v
,
312 static void process_leaf_node_dir_v2_int(inodata_t
*id
, int v
,
315 static xfs_ino_t
process_node_dir_v1(blkmap_t
*blkmap
, int *dot
,
316 int *dotdot
, inodata_t
*id
);
317 static void process_quota(int isgrp
, inodata_t
*id
,
319 static void process_rtbitmap(blkmap_t
*blkmap
);
320 static void process_rtsummary(blkmap_t
*blkmap
);
321 static xfs_ino_t
process_sf_dir_v2(xfs_dinode_t
*dip
, int *dot
,
322 int *dotdot
, inodata_t
*id
);
323 static xfs_ino_t
process_shortform_dir_v1(xfs_dinode_t
*dip
, int *dot
,
324 int *dotdot
, inodata_t
*id
);
325 static void quota_add(xfs_dqid_t grpid
, xfs_dqid_t usrid
,
326 int dq
, xfs_qcnt_t bc
, xfs_qcnt_t ic
,
328 static void quota_add1(qdata_t
**qt
, xfs_dqid_t id
, int dq
,
329 xfs_qcnt_t bc
, xfs_qcnt_t ic
,
331 static void quota_check(char *s
, qdata_t
**qt
);
332 static void quota_init(void);
333 static void scan_ag(xfs_agnumber_t agno
);
334 static void scan_freelist(xfs_agf_t
*agf
);
335 static void scan_lbtree(xfs_fsblock_t root
, int nlevels
,
336 scan_lbtree_f_t func
, dbm_t type
,
337 inodata_t
*id
, xfs_drfsbno_t
*totd
,
338 xfs_drfsbno_t
*toti
, xfs_extnum_t
*nex
,
339 blkmap_t
**blkmapp
, int isroot
,
341 static void scan_sbtree(xfs_agf_t
*agf
, xfs_agblock_t root
,
342 int nlevels
, int isroot
,
343 scan_sbtree_f_t func
, typnm_t btype
);
344 static void scanfunc_bmap(xfs_btree_lblock_t
*ablock
, int level
,
345 dbm_t type
, xfs_fsblock_t bno
,
346 inodata_t
*id
, xfs_drfsbno_t
*totd
,
347 xfs_drfsbno_t
*toti
, xfs_extnum_t
*nex
,
348 blkmap_t
**blkmapp
, int isroot
,
350 static void scanfunc_bno(xfs_btree_sblock_t
*ablock
, int level
,
351 xfs_agf_t
*agf
, xfs_agblock_t bno
,
353 static void scanfunc_cnt(xfs_btree_sblock_t
*ablock
, int level
,
354 xfs_agf_t
*agf
, xfs_agblock_t bno
,
356 static void scanfunc_ino(xfs_btree_sblock_t
*ablock
, int level
,
357 xfs_agf_t
*agf
, xfs_agblock_t bno
,
359 static void set_dbmap(xfs_agnumber_t agno
, xfs_agblock_t agbno
,
360 xfs_extlen_t len
, dbm_t type
,
361 xfs_agnumber_t c_agno
, xfs_agblock_t c_agbno
);
362 static void set_inomap(xfs_agnumber_t agno
, xfs_agblock_t agbno
,
363 xfs_extlen_t len
, inodata_t
*id
);
364 static void set_rdbmap(xfs_drfsbno_t bno
, xfs_extlen_t len
,
366 static void set_rinomap(xfs_drfsbno_t bno
, xfs_extlen_t len
,
368 static void setlink_inode(inodata_t
*id
, nlink_t nlink
, int isdir
,
371 static const cmdinfo_t blockfree_cmd
=
372 { "blockfree", NULL
, blockfree_f
, 0, 0, 0,
373 NULL
, "free block usage information", NULL
};
374 static const cmdinfo_t blockget_cmd
=
375 { "blockget", "check", blockget_f
, 0, -1, 0,
376 "[-s|-v] [-n] [-b bno]... [-i ino] ...",
377 "get block usage and check consistency", NULL
};
379 static const cmdinfo_t blocktrash_cmd
=
380 { "blocktrash", NULL
, blocktrash_f
, 0, -1, 0,
381 "[-n count] [-x minlen] [-y maxlen] [-s seed] [-0123] [-t type] ...",
382 "trash randomly selected block(s)", NULL
};
384 static const cmdinfo_t blockuse_cmd
=
385 { "blockuse", NULL
, blockuse_f
, 0, 3, 0,
386 "[-n] [-c blockcount]",
387 "print usage for current block(s)", NULL
};
388 static const cmdinfo_t ncheck_cmd
=
389 { "ncheck", NULL
, ncheck_f
, 0, -1, 0,
391 "print inode-name pairs", NULL
};
399 blist
= xrealloc(blist
, blist_size
* sizeof(bno
));
400 blist
[blist_size
- 1] = bno
;
409 id
= find_inode(ino
, 1);
411 dbprintf("-i %lld bad inode number\n", ino
);
422 if (verbose
|| id
->ilist
)
423 dbprintf("inode %lld add link, now %u\n", id
->ino
,
433 if (!nflag
|| id
->name
)
435 id
->name
= xmalloc(namelen
+ 1);
436 memcpy(id
->name
, name
, namelen
);
437 id
->name
[namelen
] = '\0';
447 pid
= find_inode(parent
, 1);
449 if (verbose
|| id
->ilist
|| (pid
&& pid
->ilist
))
450 dbprintf("inode %lld parent %lld\n", id
->ino
, parent
);
463 *entp
= ent
= xrealloc(ent
, BLKENT_SIZE(c
+ ent
->nblks
));
464 for (i
= 0; i
< c
; i
++)
465 ent
->blks
[ent
->nblks
+ i
] = b
+ i
;
478 ent
= xmalloc(BLKENT_SIZE(c
));
481 for (i
= 0; i
< c
; i
++)
482 ent
->blks
[i
] = b
+ i
;
497 newent
= xmalloc(BLKENT_SIZE(oldent
->nblks
+ c
));
498 newent
->nblks
= oldent
->nblks
+ c
;
499 newent
->startoff
= oldent
->startoff
- c
;
500 for (i
= 0; i
< c
; i
++)
501 newent
->blks
[i
] = b
+ c
;
502 for (; i
< oldent
->nblks
+ c
; i
++)
503 newent
->blks
[i
] = oldent
->blks
[i
- c
];
516 blkmap
= xmalloc(BLKMAP_SIZE(nex
));
517 blkmap
->naents
= nex
;
529 for (i
= 0, entp
= blkmap
->ents
; i
< blkmap
->nents
; i
++, entp
++)
543 for (i
= 0, entp
= blkmap
->ents
; i
< blkmap
->nents
; i
++, entp
++) {
545 if (o
>= ent
->startoff
&& o
< ent
->startoff
+ ent
->nblks
)
546 return ent
->blks
[o
- ent
->startoff
];
565 for (i
= nex
= 0, bmp
= NULL
, entp
= blkmap
->ents
;
569 if (ent
->startoff
>= o
+ nb
)
571 if (ent
->startoff
+ ent
->nblks
<= o
)
573 for (ento
= ent
->startoff
;
574 ento
< ent
->startoff
+ ent
->nblks
&& ento
< o
+ nb
;
579 bmp
[nex
- 1].startoff
+ bmp
[nex
- 1].blockcount
==
581 bmp
[nex
- 1].startblock
+ bmp
[nex
- 1].blockcount
==
582 ent
->blks
[ento
- ent
->startoff
])
583 bmp
[nex
- 1].blockcount
++;
585 bmp
= realloc(bmp
, ++nex
* sizeof(*bmp
));
586 bmp
[nex
- 1].startoff
= ento
;
587 bmp
[nex
- 1].startblock
=
588 ent
->blks
[ento
- ent
->startoff
];
589 bmp
[nex
- 1].blockcount
= 1;
590 bmp
[nex
- 1].flag
= 0;
609 idx
= (int)(entp
- blkmap
->ents
);
610 if (blkmap
->naents
== blkmap
->nents
) {
611 blkmap
= xrealloc(blkmap
, BLKMAP_SIZE(blkmap
->nents
+ 1));
615 for (i
= blkmap
->nents
; i
> idx
; i
--)
616 blkmap
->ents
[i
] = blkmap
->ents
[i
- 1];
617 blkmap
->ents
[idx
] = newent
;
629 ent
= blkmap
->ents
[blkmap
->nents
- 1];
630 return ent
->startoff
+ ent
->nblks
;
644 if (o
== NULLFILEOFF
) {
646 ent
= blkmap
->ents
[0];
647 return ent
->startoff
;
649 entp
= &blkmap
->ents
[*t
];
651 if (o
< ent
->startoff
+ ent
->nblks
- 1)
654 if (entp
>= &blkmap
->ents
[blkmap
->nents
])
658 return ent
->startoff
;
673 for (entp
= blkmap
->ents
; entp
< &blkmap
->ents
[blkmap
->nents
]; entp
++) {
675 if (o
< ent
->startoff
- 1) {
676 ent
= blkent_new(o
, b
, 1);
677 blkmap_grow(blkmapp
, entp
, ent
);
680 if (o
== ent
->startoff
- 1) {
681 blkent_prepend(entp
, b
, 1);
684 if (o
>= ent
->startoff
&& o
< ent
->startoff
+ ent
->nblks
) {
685 ent
->blks
[o
- ent
->startoff
] = b
;
688 if (o
> ent
->startoff
+ ent
->nblks
)
690 blkent_append(entp
, b
, 1);
691 if (entp
== &blkmap
->ents
[blkmap
->nents
- 1])
695 if (ent
->startoff
+ ent
->nblks
< nextent
->startoff
)
697 blkent_append(entp
, nextent
->blks
[0], nextent
->nblks
);
698 blkmap_shrink(blkmap
, &entp
[1]);
701 ent
= blkent_new(o
, b
, 1);
702 blkmap_grow(blkmapp
, entp
, ent
);
718 if (!blkmap
->nents
) {
719 blkmap
->ents
[0] = blkent_new(o
, b
, c
);
723 entp
= &blkmap
->ents
[blkmap
->nents
- 1];
725 if (ent
->startoff
+ ent
->nblks
== o
) {
726 blkent_append(entp
, b
, c
);
729 if (ent
->startoff
+ ent
->nblks
< o
) {
730 ent
= blkent_new(o
, b
, c
);
731 blkmap_grow(blkmapp
, &blkmap
->ents
[blkmap
->nents
], ent
);
734 for (i
= 0; i
< c
; i
++)
735 blkmap_set_blk(blkmapp
, o
+ i
, b
+ i
);
747 idx
= (int)(entp
- blkmap
->ents
);
748 for (i
= idx
+ 1; i
< blkmap
->nents
; i
++)
749 blkmap
->ents
[i
] = blkmap
->ents
[i
- 1];
763 dbprintf("block usage information not allocated\n");
766 rt
= mp
->m_sb
.sb_rextents
!= 0;
767 for (c
= 0; c
< mp
->m_sb
.sb_agcount
; c
++) {
777 sumcompute
= sumfile
= NULL
;
789 * Check consistency of xfs filesystem contents.
801 dbprintf("already have block usage information\n");
804 if (!init(argc
, argv
))
806 oldprefix
= dbprefix
;
808 for (agno
= 0, sbyell
= 0; agno
< mp
->m_sb
.sb_agcount
; agno
++) {
810 if (sbver_err
> 4 && !sbyell
&& sbver_err
>= agno
) {
812 dbprintf("WARNING: this may be a newer XFS "
823 dbprefix
= oldprefix
;
827 for (agno
= 0; agno
< mp
->m_sb
.sb_agcount
; agno
++) {
829 * Check that there are no blocks either
830 * a) unaccounted for or
831 * b) bno-free but not cnt-free
833 checknot_dbmap(agno
, 0, mp
->m_sb
.sb_agblocks
,
834 (1 << DBM_UNKNOWN
) | (1 << DBM_FREE1
));
835 check_linkcounts(agno
);
837 if (mp
->m_sb
.sb_rblocks
) {
839 (xfs_extlen_t
)(mp
->m_sb
.sb_rextents
*
840 mp
->m_sb
.sb_rextsize
),
844 if (mp
->m_sb
.sb_icount
!= icount
) {
846 dbprintf("sb_icount %lld, counted %lld\n",
847 mp
->m_sb
.sb_icount
, icount
);
850 if (mp
->m_sb
.sb_ifree
!= ifree
) {
852 dbprintf("sb_ifree %lld, counted %lld\n",
853 mp
->m_sb
.sb_ifree
, ifree
);
856 if (mp
->m_sb
.sb_fdblocks
!= fdblocks
) {
858 dbprintf("sb_fdblocks %lld, counted %lld\n",
859 mp
->m_sb
.sb_fdblocks
, fdblocks
);
862 if (mp
->m_sb
.sb_frextents
!= frextents
) {
864 dbprintf("sb_frextents %lld, counted %lld\n",
865 mp
->m_sb
.sb_frextents
, frextents
);
868 if ((sbversion
& XFS_SB_VERSION_ATTRBIT
) &&
869 !XFS_SB_VERSION_HASATTR(&mp
->m_sb
)) {
871 dbprintf("sb versionnum missing attr bit %x\n",
872 XFS_SB_VERSION_ATTRBIT
);
875 if ((sbversion
& XFS_SB_VERSION_NLINKBIT
) &&
876 !XFS_SB_VERSION_HASNLINK(&mp
->m_sb
)) {
878 dbprintf("sb versionnum missing nlink bit %x\n",
879 XFS_SB_VERSION_NLINKBIT
);
882 if ((sbversion
& XFS_SB_VERSION_QUOTABIT
) &&
883 !XFS_SB_VERSION_HASQUOTA(&mp
->m_sb
)) {
885 dbprintf("sb versionnum missing quota bit %x\n",
886 XFS_SB_VERSION_QUOTABIT
);
889 if (!(sbversion
& XFS_SB_VERSION_ALIGNBIT
) &&
890 XFS_SB_VERSION_HASALIGN(&mp
->m_sb
)) {
892 dbprintf("sb versionnum extra align bit %x\n",
893 XFS_SB_VERSION_ALIGNBIT
);
897 quota_check("user", qudata
);
899 quota_check("group", qgdata
);
900 if (sbver_err
> mp
->m_sb
.sb_agcount
/ 2)
901 dbprintf("WARNING: this may be a newer XFS filesystem.\n");
904 dbprefix
= oldprefix
;
909 typedef struct ltab
{
930 static char *modestr
[] = {
931 "zeroed", "set", "flipped", "randomized"
934 len
= (int)((random() % (ltabp
->max
- ltabp
->min
+ 1)) + ltabp
->min
);
935 offset
= (int)(random() % (int)(mp
->m_sb
.sb_blocksize
* NBBY
));
938 set_cur(&typtab
[DBM_UNKNOWN
],
939 XFS_AGB_TO_DADDR(mp
, agno
, agbno
), blkbb
, DB_RING_IGN
, NULL
);
940 if ((buf
= iocur_top
->data
) == NULL
) {
941 dbprintf("can't read block %u/%u for trashing\n", agno
, agbno
);
945 for (bitno
= 0; bitno
< len
; bitno
++) {
946 bit
= (offset
+ bitno
) % (mp
->m_sb
.sb_blocksize
* NBBY
);
958 newbit
= (buf
[byte
] & mask
) == 0;
961 newbit
= (int)random() & 1;
971 printf("blocktrash: %u/%u %s block %d bit%s starting %d:%d %s\n",
972 agno
, agbno
, typename
[type
], len
, len
== 1 ? "" : "s",
973 offset
/ NBBY
, offset
% NBBY
, modestr
[mode
]);
984 xfs_drfsbno_t blocks
;
1003 dbprintf("must run blockget first\n");
1011 gettimeofday(&now
, NULL
);
1012 seed
= (unsigned int)(now
.tv_sec
^ now
.tv_usec
);
1015 goodmask
= (1 << DBM_AGF
) |
1019 (1 << DBM_BTBMAPA
) |
1020 (1 << DBM_BTBMAPD
) |
1027 (1 << DBM_RTBITMAP
) |
1030 while ((c
= getopt(argc
, argv
, "0123n:s:t:x:y:")) != EOF
) {
1045 count
= (int)strtol(optarg
, &p
, 0);
1046 if (*p
!= '\0' || count
<= 0) {
1047 dbprintf("bad blocktrash count %s\n", optarg
);
1052 seed
= (uint
)strtoul(optarg
, &p
, 0);
1056 for (i
= 0; typename
[i
]; i
++) {
1057 if (strcmp(typename
[i
], optarg
) == 0)
1060 if (!typename
[i
] || (((1 << i
) & goodmask
) == 0)) {
1061 dbprintf("bad blocktrash type %s\n", optarg
);
1067 min
= (int)strtol(optarg
, &p
, 0);
1068 if (*p
!= '\0' || min
<= 0 ||
1069 min
> mp
->m_sb
.sb_blocksize
* NBBY
) {
1070 dbprintf("bad blocktrash min %s\n", optarg
);
1075 max
= (int)strtol(optarg
, &p
, 0);
1076 if (*p
!= '\0' || max
<= 0 ||
1077 max
> mp
->m_sb
.sb_blocksize
* NBBY
) {
1078 dbprintf("bad blocktrash max %s\n", optarg
);
1083 dbprintf("bad option for blocktrash command\n");
1088 dbprintf("bad min/max for blocktrash command\n");
1093 lentab
= xmalloc(sizeof(ltab_t
));
1094 lentab
->min
= lentab
->max
= min
;
1096 for (i
= min
+ 1; i
<= max
; i
++) {
1097 if ((i
& (i
- 1)) == 0) {
1098 lentab
= xrealloc(lentab
,
1099 sizeof(ltab_t
) * (lentablen
+ 1));
1100 lentab
[lentablen
].min
= lentab
[lentablen
].max
= i
;
1103 lentab
[lentablen
- 1].max
= i
;
1105 for (blocks
= 0, agno
= 0; agno
< mp
->m_sb
.sb_agcount
; agno
++) {
1106 for (agbno
= 0, p
= dbmap
[agno
];
1107 agbno
< mp
->m_sb
.sb_agblocks
;
1109 if ((1 << *p
) & tmask
)
1114 dbprintf("blocktrash: no matching blocks\n");
1118 dbprintf("blocktrash: seed %u\n", seed
);
1120 for (i
= 0; i
< count
; i
++) {
1121 randb
= (xfs_drfsbno_t
)((((__int64_t
)random() << 32) |
1122 random()) % blocks
);
1123 for (bi
= 0, agno
= 0, done
= 0;
1124 !done
&& agno
< mp
->m_sb
.sb_agcount
;
1126 for (agbno
= 0, p
= dbmap
[agno
];
1127 agbno
< mp
->m_sb
.sb_agblocks
;
1129 if (!((1 << *p
) & tmask
))
1133 blocktrash_b(agno
, agbno
, (dbm_t
)*p
,
1134 &lentab
[random() % lentablen
], mode
);
1150 xfs_agblock_t agbno
;
1151 xfs_agnumber_t agno
;
1161 dbprintf("must run blockget first\n");
1167 fsb
= XFS_DADDR_TO_FSB(mp
, iocur_top
->off
>> BBSHIFT
);
1168 agno
= XFS_FSB_TO_AGNO(mp
, fsb
);
1169 end
= agbno
= XFS_FSB_TO_AGBNO(mp
, fsb
);
1170 while ((c
= getopt(argc
, argv
, "c:n")) != EOF
) {
1173 count
= (int)strtol(optarg
, &p
, 0);
1174 end
= agbno
+ count
- 1;
1175 if (*p
!= '\0' || count
<= 0 ||
1176 end
>= mp
->m_sb
.sb_agblocks
) {
1177 dbprintf("bad blockuse count %s\n", optarg
);
1183 dbprintf("must run blockget -n first\n");
1189 dbprintf("bad option for blockuse command\n");
1193 while (agbno
<= end
) {
1194 p
= &dbmap
[agno
][agbno
];
1195 i
= inomap
[agno
][agbno
];
1196 dbprintf("block %llu (%u/%u) type %s",
1197 (xfs_dfsbno_t
)XFS_AGB_TO_FSB(mp
, agno
, agbno
),
1198 agno
, agbno
, typename
[(dbm_t
)*p
]);
1200 dbprintf(" inode %lld", i
->ino
);
1201 if (shownames
&& (p
= inode_name(i
->ino
, NULL
))) {
1218 for (i
= 0; i
< blist_size
; i
++) {
1219 if (blist
[i
] == bno
)
1227 xfs_agnumber_t agno
,
1228 xfs_agblock_t agbno
,
1235 for (i
= 0, p
= &dbmap
[agno
][agbno
]; i
< len
; i
++, p
++) {
1236 if ((dbm_t
)*p
!= type
) {
1237 if (!sflag
|| CHECK_BLISTA(agno
, agbno
+ i
))
1238 dbprintf("block %u/%u expected type %s got "
1240 agno
, agbno
+ i
, typename
[type
],
1241 typename
[(dbm_t
)*p
]);
1250 add_command(&blockfree_cmd
);
1251 add_command(&blockget_cmd
);
1253 add_command(&blocktrash_cmd
);
1255 add_command(&blockuse_cmd
);
1256 add_command(&ncheck_cmd
);
1261 xfs_agnumber_t agno
,
1262 xfs_agblock_t agbno
,
1270 if (!check_range(agno
, agbno
, len
)) {
1271 dbprintf("blocks %u/%u..%u claimed by inode %lld\n",
1272 agno
, agbno
, agbno
+ len
- 1, c_ino
);
1275 for (i
= 0, rval
= 1, idp
= &inomap
[agno
][agbno
]; i
< len
; i
++, idp
++) {
1277 if (!sflag
|| (*idp
)->ilist
||
1278 CHECK_BLISTA(agno
, agbno
+ i
))
1279 dbprintf("block %u/%u claimed by inode %lld, "
1280 "previous inum %lld\n",
1281 agno
, agbno
+ i
, c_ino
, (*idp
)->ino
);
1291 xfs_agnumber_t agno
)
1299 for (idx
= 0; idx
< inodata_hash_size
; ht
++, idx
++) {
1302 if (ep
->link_set
!= ep
->link_add
|| ep
->link_set
== 0) {
1303 path
= inode_name(ep
->ino
, NULL
);
1304 if (!path
&& ep
->link_add
)
1305 path
= xstrdup("?");
1306 if (!sflag
|| ep
->ilist
) {
1308 dbprintf("link count mismatch "
1309 "for inode %lld (name "
1315 else if (ep
->link_set
)
1316 dbprintf("disconnected inode "
1318 ep
->ino
, ep
->link_set
);
1320 dbprintf("allocated inode %lld "
1321 "has 0 link count\n",
1327 } else if (verbose
|| ep
->ilist
) {
1328 path
= inode_name(ep
->ino
, NULL
);
1330 dbprintf("inode %lld name %s\n",
1343 xfs_agnumber_t agno
,
1344 xfs_agblock_t agbno
,
1349 if (agno
>= mp
->m_sb
.sb_agcount
||
1350 agbno
+ len
- 1 >= mp
->m_sb
.sb_agblocks
) {
1351 for (i
= 0; i
< len
; i
++) {
1352 if (!sflag
|| CHECK_BLISTA(agno
, agbno
+ i
))
1353 dbprintf("block %u/%u out of range\n",
1371 for (i
= 0, p
= &dbmap
[mp
->m_sb
.sb_agcount
][bno
]; i
< len
; i
++, p
++) {
1372 if ((dbm_t
)*p
!= type
) {
1373 if (!sflag
|| CHECK_BLIST(bno
+ i
))
1374 dbprintf("rtblock %llu expected type %s got "
1376 bno
+ i
, typename
[type
],
1377 typename
[(dbm_t
)*p
]);
1393 if (!check_rrange(bno
, len
)) {
1394 dbprintf("rtblocks %llu..%llu claimed by inode %lld\n",
1395 bno
, bno
+ len
- 1, c_ino
);
1398 for (i
= 0, rval
= 1, idp
= &inomap
[mp
->m_sb
.sb_agcount
][bno
];
1402 if (!sflag
|| (*idp
)->ilist
|| CHECK_BLIST(bno
+ i
))
1403 dbprintf("rtblock %llu claimed by inode %lld, "
1404 "previous inum %lld\n",
1405 bno
+ i
, c_ino
, (*idp
)->ino
);
1418 id
= find_inode(mp
->m_sb
.sb_rootino
, 0);
1421 dbprintf("root inode %lld is missing\n",
1422 mp
->m_sb
.sb_rootino
);
1424 } else if (!id
->isdir
) {
1425 if (!sflag
|| id
->ilist
)
1426 dbprintf("root inode %lld is not a directory\n",
1427 mp
->m_sb
.sb_rootino
);
1439 if (bno
+ len
- 1 >= mp
->m_sb
.sb_rblocks
) {
1440 for (i
= 0; i
< len
; i
++) {
1441 if (!sflag
|| CHECK_BLIST(bno
+ i
))
1442 dbprintf("rtblock %llu out of range\n",
1453 xfs_agnumber_t agno
,
1454 xfs_agblock_t agbno
,
1458 xfs_agnumber_t c_agno
,
1459 xfs_agblock_t c_agbno
)
1465 if (!check_range(agno
, agbno
, len
)) {
1466 dbprintf("blocks %u/%u..%u claimed by block %u/%u\n", agno
,
1467 agbno
, agbno
+ len
- 1, c_agno
, c_agbno
);
1470 check_dbmap(agno
, agbno
, len
, type1
);
1471 mayprint
= verbose
| blist_size
;
1472 for (i
= 0, p
= &dbmap
[agno
][agbno
]; i
< len
; i
++, p
++) {
1474 if (mayprint
&& (verbose
|| CHECK_BLISTA(agno
, agbno
+ i
)))
1475 dbprintf("setting block %u/%u to %s\n", agno
, agbno
+ i
,
1491 if (!check_rrange(bno
, len
))
1493 check_rdbmap(bno
, len
, type1
);
1494 mayprint
= verbose
| blist_size
;
1495 for (i
= 0, p
= &dbmap
[mp
->m_sb
.sb_agcount
][bno
]; i
< len
; i
++, p
++) {
1497 if (mayprint
&& (verbose
|| CHECK_BLIST(bno
+ i
)))
1498 dbprintf("setting rtblock %llu to %s\n",
1499 bno
+ i
, typename
[type2
]);
1513 for (log
= 0; log
< mp
->m_rsumlevels
; log
++) {
1515 bno
< mp
->m_sb
.sb_rbmblocks
;
1516 bno
++, csp
++, fsp
++) {
1519 dbprintf("rt summary mismatch, size %d "
1520 "block %llu, file: %d, "
1522 log
, bno
, *fsp
, *csp
);
1531 xfs_agnumber_t agno
,
1532 xfs_agblock_t agbno
,
1539 if (!check_range(agno
, agbno
, len
))
1541 for (i
= 0, p
= &dbmap
[agno
][agbno
]; i
< len
; i
++, p
++) {
1542 if ((1 << *p
) & typemask
) {
1543 if (!sflag
|| CHECK_BLISTA(agno
, agbno
+ i
))
1544 dbprintf("block %u/%u type %s not expected\n",
1545 agno
, agbno
+ i
, typename
[(dbm_t
)*p
]);
1560 if (!check_rrange(bno
, len
))
1562 for (i
= 0, p
= &dbmap
[mp
->m_sb
.sb_agcount
][bno
]; i
< len
; i
++, p
++) {
1563 if ((1 << *p
) & typemask
) {
1564 if (!sflag
|| CHECK_BLIST(bno
+ i
))
1565 dbprintf("rtblock %llu type %s not expected\n",
1566 bno
+ i
, typename
[(dbm_t
)*p
]);
1575 xfs_dir2_dataptr_t addr
)
1580 i
= DIR_HASH_FUNC(hash
, addr
);
1581 p
= malloc(sizeof(*p
));
1582 p
->next
= dirhash
[i
];
1584 p
->entry
.hashval
= hash
;
1585 p
->entry
.address
= addr
;
1597 for (i
= 0; i
< DIR_HASH_SIZE
; i
++) {
1598 for (p
= dirhash
[i
]; p
; p
= p
->next
) {
1601 if (!sflag
|| id
->ilist
|| v
)
1602 dbprintf("dir ino %lld missing leaf entry for "
1604 id
->ino
, p
->entry
.hashval
,
1618 for (i
= 0; i
< DIR_HASH_SIZE
; i
++) {
1619 for (p
= dirhash
[i
]; p
; p
= n
) {
1631 dirhash
= calloc(DIR_HASH_SIZE
, sizeof(*dirhash
));
1637 xfs_dir2_dataptr_t addr
)
1642 i
= DIR_HASH_FUNC(hash
, addr
);
1643 for (p
= dirhash
[i
]; p
; p
= p
->next
) {
1644 if (p
->entry
.hashval
== hash
&& p
->entry
.address
== addr
) {
1660 xfs_agnumber_t agno
;
1665 agno
= XFS_INO_TO_AGNO(mp
, ino
);
1666 agino
= XFS_INO_TO_AGINO(mp
, ino
);
1667 if (agno
>= mp
->m_sb
.sb_agcount
||
1668 XFS_AGINO_TO_INO(mp
, agno
, agino
) != ino
)
1670 htab
= inodata
[agno
];
1671 ih
= agino
% inodata_hash_size
;
1674 if (ent
->ino
== ino
)
1680 ent
= xcalloc(1, sizeof(*ent
));
1682 ent
->next
= htab
[ih
];
1689 xfs_agnumber_t agno
)
1697 for (i
= 0; i
< inodata_hash_size
; i
++) {
1720 if (mp
->m_sb
.sb_magicnum
!= XFS_SB_MAGIC
) {
1721 dbprintf("bad superblock magic number %x, giving up\n",
1722 mp
->m_sb
.sb_magicnum
);
1725 rt
= mp
->m_sb
.sb_rextents
!= 0;
1726 dbmap
= xmalloc((mp
->m_sb
.sb_agcount
+ rt
) * sizeof(*dbmap
));
1727 inomap
= xmalloc((mp
->m_sb
.sb_agcount
+ rt
) * sizeof(*inomap
));
1728 inodata
= xmalloc(mp
->m_sb
.sb_agcount
* sizeof(*inodata
));
1730 (int)MAX(MIN(mp
->m_sb
.sb_icount
/
1731 (INODATA_AVG_HASH_LENGTH
* mp
->m_sb
.sb_agcount
),
1732 MAX_INODATA_HASH_SIZE
),
1733 MIN_INODATA_HASH_SIZE
);
1734 for (c
= 0; c
< mp
->m_sb
.sb_agcount
; c
++) {
1735 dbmap
[c
] = xcalloc(mp
->m_sb
.sb_agblocks
, sizeof(**dbmap
));
1736 inomap
[c
] = xcalloc(mp
->m_sb
.sb_agblocks
, sizeof(**inomap
));
1737 inodata
[c
] = xcalloc(inodata_hash_size
, sizeof(**inodata
));
1740 dbmap
[c
] = xcalloc(mp
->m_sb
.sb_rblocks
, sizeof(**dbmap
));
1741 inomap
[c
] = xcalloc(mp
->m_sb
.sb_rblocks
, sizeof(**inomap
));
1742 sumfile
= xcalloc(mp
->m_rsumsize
, 1);
1743 sumcompute
= xcalloc(mp
->m_rsumsize
, 1);
1745 nflag
= sflag
= verbose
= optind
= 0;
1746 while ((c
= getopt(argc
, argv
, "b:i:npsv")) != EOF
) {
1749 bno
= strtoll(optarg
, NULL
, 10);
1753 ino
= strtoll(optarg
, NULL
, 10);
1769 dbprintf("bad option for blockget command\n");
1773 error
= sbver_err
= serious_error
= 0;
1774 fdblocks
= frextents
= icount
= ifree
= 0;
1775 sbversion
= XFS_SB_VERSION_4
;
1776 if (mp
->m_sb
.sb_inoalignmt
)
1777 sbversion
|= XFS_SB_VERSION_ALIGNBIT
;
1778 if ((mp
->m_sb
.sb_uquotino
&& mp
->m_sb
.sb_uquotino
!= NULLFSINO
) ||
1779 (mp
->m_sb
.sb_gquotino
&& mp
->m_sb
.sb_gquotino
!= NULLFSINO
))
1780 sbversion
|= XFS_SB_VERSION_QUOTABIT
;
1794 id
= find_inode(ino
, 0);
1799 if (id
->name
== NULL
)
1801 path
= xstrdup(id
->name
);
1802 while (id
->parent
) {
1804 if (id
->name
== NULL
)
1806 npath
= prepend_path(path
, id
->name
);
1818 xfs_agnumber_t agno
;
1831 if (!inodata
|| !nflag
) {
1832 dbprintf("must run blockget -n first\n");
1835 security
= optind
= ilist_size
= 0;
1837 while ((c
= getopt(argc
, argv
, "i:s")) != EOF
) {
1840 ino
= strtoll(optarg
, NULL
, 10);
1841 ilist
= xrealloc(ilist
, (ilist_size
+ 1) *
1843 ilist
[ilist_size
++] = ino
;
1849 dbprintf("bad option -%c for ncheck command\n", c
);
1854 for (ilp
= ilist
; ilp
< &ilist
[ilist_size
]; ilp
++) {
1856 if ((p
= inode_name(ino
, &hp
))) {
1857 dbprintf("%11llu %s", ino
, p
);
1867 for (agno
= 0; agno
< mp
->m_sb
.sb_agcount
; agno
++) {
1869 for (i
= 0; i
< inodata_hash_size
; i
++) {
1871 for (hp
= ht
[i
]; hp
; hp
= hp
->next
) {
1872 ino
= XFS_AGINO_TO_INO(mp
, agno
, hp
->ino
);
1873 p
= inode_name(ino
, &id
);
1876 if (!security
|| id
->security
) {
1877 dbprintf("%11llu %s", ino
, p
);
1897 len
= (int)(strlen(oldpath
) + strlen(parent
) + 2);
1898 path
= xmalloc(len
);
1899 snprintf(path
, len
, "%s/%s", parent
, oldpath
);
1904 process_block_dir_v2(
1918 nex
= blkmap_getn(blkmap
, 0, mp
->m_dirblkfsbs
, &bmp
);
1919 v
= id
->ilist
|| verbose
;
1922 dbprintf("block 0 for directory inode %lld is "
1930 make_bbmap(&bbmap
, nex
, bmp
);
1931 set_cur(&typtab
[TYP_DIR
], XFS_FSB_TO_DADDR(mp
, bmp
->startblock
),
1932 mp
->m_dirblkfsbs
* blkbb
, DB_RING_IGN
, nex
> 1 ? &bbmap
: NULL
);
1933 for (x
= 0; !v
&& x
< nex
; x
++) {
1934 for (b
= bmp
[x
].startblock
;
1935 !v
&& b
< bmp
[x
].startblock
+ bmp
[x
].blockcount
;
1940 if (iocur_top
->data
== NULL
) {
1941 if (!sflag
|| id
->ilist
|| v
)
1942 dbprintf("can't read block 0 for directory inode "
1949 parent
= process_data_dir_v2(dot
, dotdot
, id
, v
, mp
->m_dirdatablk
,
1951 dir_hash_check(id
, v
);
1958 process_bmbt_reclist(
1959 xfs_bmbt_rec_32_t
*rp
,
1966 xfs_agblock_t agbno
;
1967 xfs_agnumber_t agno
;
1973 xfs_agblock_t iagbno
;
1974 xfs_agnumber_t iagno
;
1981 v
= verbose
|| id
->ilist
;
1982 iagno
= XFS_INO_TO_AGNO(mp
, id
->ino
);
1983 iagbno
= XFS_INO_TO_AGBNO(mp
, id
->ino
);
1984 for (i
= 0; i
< numrecs
; i
++, rp
++) {
1985 convert_extent((xfs_bmbt_rec_64_t
*)rp
, &o
, &s
, &c
, &f
);
1987 dbprintf("inode %lld extent [%lld,%lld,%lld,%d]\n",
1988 id
->ino
, o
, s
, c
, f
);
1989 if (!sflag
&& i
> 0 && op
+ cp
> o
)
1990 dbprintf("bmap rec out of order, inode %lld entry %d\n",
1994 if (type
== DBM_RTDATA
) {
1995 if (!sflag
&& s
>= mp
->m_sb
.sb_rblocks
) {
1996 dbprintf("inode %lld bad rt block number %lld, "
2001 } else if (!sflag
) {
2002 agno
= XFS_FSB_TO_AGNO(mp
, s
);
2003 agbno
= XFS_FSB_TO_AGBNO(mp
, s
);
2004 if (agno
>= mp
->m_sb
.sb_agcount
||
2005 agbno
>= mp
->m_sb
.sb_agblocks
) {
2006 dbprintf("inode %lld bad block number %lld "
2007 "[%d,%d], offset %lld\n",
2008 id
->ino
, s
, agno
, agbno
, o
);
2011 if (agbno
+ c
- 1 >= mp
->m_sb
.sb_agblocks
) {
2012 dbprintf("inode %lld bad block number %lld "
2013 "[%d,%d], offset %lld\n",
2014 id
->ino
, s
+ c
- 1, agno
,
2015 agbno
+ (xfs_agblock_t
)c
- 1, o
);
2019 if (blkmapp
&& *blkmapp
)
2020 blkmap_set_ext(blkmapp
, (xfs_fileoff_t
)o
,
2021 (xfs_fsblock_t
)s
, (xfs_extlen_t
)c
);
2022 if (type
== DBM_RTDATA
) {
2023 set_rdbmap((xfs_fsblock_t
)s
, (xfs_extlen_t
)c
,
2025 set_rinomap((xfs_fsblock_t
)s
, (xfs_extlen_t
)c
, id
);
2026 for (b
= (xfs_fsblock_t
)s
;
2027 blist_size
&& b
< s
+ c
;
2030 dbprintf("inode %lld block %lld at "
2032 id
->ino
, (xfs_dfsbno_t
)b
, o
);
2035 agno
= XFS_FSB_TO_AGNO(mp
, (xfs_fsblock_t
)s
);
2036 agbno
= XFS_FSB_TO_AGBNO(mp
, (xfs_fsblock_t
)s
);
2037 set_dbmap(agno
, agbno
, (xfs_extlen_t
)c
, type
, iagno
,
2039 set_inomap(agno
, agbno
, (xfs_extlen_t
)c
, id
);
2040 for (b
= (xfs_fsblock_t
)s
;
2041 blist_size
&& b
< s
+ c
;
2042 b
++, o
++, agbno
++) {
2044 dbprintf("inode %lld block %lld at "
2046 id
->ino
, (xfs_dfsbno_t
)b
, o
);
2058 xfs_drfsbno_t
*totd
,
2059 xfs_drfsbno_t
*toti
,
2064 xfs_bmdr_block_t
*dib
;
2067 xfs_bmbt_rec_32_t
*rp
;
2069 dib
= (xfs_bmdr_block_t
*)XFS_DFORK_PTR_ARCH(dip
, whichfork
, ARCH_NOCONVERT
);
2070 if (INT_GET(dib
->bb_level
, ARCH_CONVERT
) >= XFS_BM_MAXLEVELS(mp
, whichfork
)) {
2071 if (!sflag
|| id
->ilist
)
2072 dbprintf("level for ino %lld %s fork bmap root too "
2075 whichfork
== XFS_DATA_FORK
? "data" : "attr",
2076 INT_GET(dib
->bb_level
, ARCH_CONVERT
));
2080 if (INT_GET(dib
->bb_numrecs
, ARCH_CONVERT
) >
2081 XFS_BTREE_BLOCK_MAXRECS(XFS_DFORK_SIZE_ARCH(dip
, mp
, whichfork
, ARCH_NOCONVERT
),
2082 xfs_bmdr
, INT_GET(dib
->bb_level
, ARCH_CONVERT
) == 0)) {
2083 if (!sflag
|| id
->ilist
)
2084 dbprintf("numrecs for ino %lld %s fork bmap root too "
2087 whichfork
== XFS_DATA_FORK
? "data" : "attr",
2088 INT_GET(dib
->bb_numrecs
, ARCH_CONVERT
));
2092 if (INT_GET(dib
->bb_level
, ARCH_CONVERT
) == 0) {
2093 rp
= (xfs_bmbt_rec_32_t
*)XFS_BTREE_REC_ADDR(
2094 XFS_DFORK_SIZE_ARCH(dip
, mp
, whichfork
, ARCH_NOCONVERT
),
2096 XFS_BTREE_BLOCK_MAXRECS(XFS_DFORK_SIZE(dip
, mp
,
2099 process_bmbt_reclist(rp
, INT_GET(dib
->bb_numrecs
, ARCH_CONVERT
), type
, id
, totd
,
2101 *nex
+= INT_GET(dib
->bb_numrecs
, ARCH_CONVERT
);
2104 pp
= XFS_BTREE_PTR_ADDR(XFS_DFORK_SIZE_ARCH(dip
, mp
, whichfork
, ARCH_NOCONVERT
),
2106 XFS_BTREE_BLOCK_MAXRECS(XFS_DFORK_SIZE(dip
, mp
,
2109 for (i
= 0; i
< INT_GET(dib
->bb_numrecs
, ARCH_CONVERT
); i
++)
2110 scan_lbtree((xfs_fsblock_t
)INT_GET(pp
[i
], ARCH_CONVERT
), INT_GET(dib
->bb_level
, ARCH_CONVERT
),
2111 scanfunc_bmap
, type
, id
, totd
, toti
, nex
,
2113 whichfork
== XFS_DATA_FORK
?
2114 TYP_BMAPBTD
: TYP_BMAPBTA
);
2117 XFS_DFORK_SIZE_ARCH(dip
, mp
, whichfork
, ARCH_NOCONVERT
) / sizeof(xfs_bmbt_rec_t
)) {
2118 if (!sflag
|| id
->ilist
)
2119 dbprintf("extent count for ino %lld %s fork too low "
2120 "(%d) for file format\n",
2122 whichfork
== XFS_DATA_FORK
? "data" : "attr",
2129 process_data_dir_v2(
2135 freetab_t
**freetabp
)
2137 xfs_dir2_dataptr_t addr
;
2138 xfs_dir2_data_free_t
*bf
;
2140 xfs_dir2_block_t
*block
;
2141 xfs_dir2_block_tail_t
*btp
= NULL
;
2144 xfs_dir2_data_t
*data
;
2146 xfs_dir2_data_entry_t
*dep
;
2147 xfs_dir2_data_free_t
*dfp
;
2148 xfs_dir2_data_unused_t
*dup
;
2156 xfs_dir2_leaf_entry_t
*lep
= NULL
;
2158 xfs_ino_t parent
= 0;
2162 xfs_dir2_data_off_t
*tagp
;
2164 data
= iocur_top
->data
;
2165 block
= iocur_top
->data
;
2166 if (INT_GET(block
->hdr
.magic
, ARCH_CONVERT
) != XFS_DIR2_BLOCK_MAGIC
&&
2167 INT_GET(data
->hdr
.magic
, ARCH_CONVERT
) != XFS_DIR2_DATA_MAGIC
) {
2169 dbprintf("bad directory data magic # %#x for dir ino "
2171 INT_GET(data
->hdr
.magic
, ARCH_CONVERT
), id
->ino
, dabno
);
2175 db
= XFS_DIR2_DA_TO_DB(mp
, dabno
);
2176 bf
= data
->hdr
.bestfree
;
2177 ptr
= (char *)data
->u
;
2178 if (INT_GET(block
->hdr
.magic
, ARCH_CONVERT
) == XFS_DIR2_BLOCK_MAGIC
) {
2179 btp
= XFS_DIR2_BLOCK_TAIL_P(mp
, block
);
2180 lep
= XFS_DIR2_BLOCK_LEAF_P_ARCH(btp
, ARCH_CONVERT
);
2181 endptr
= (char *)lep
;
2182 if (endptr
<= ptr
|| endptr
> (char *)btp
) {
2183 endptr
= (char *)data
+ mp
->m_dirblksize
;
2186 dbprintf("bad block directory tail for dir ino "
2192 endptr
= (char *)data
+ mp
->m_dirblksize
;
2193 bf_err
= lastfree_err
= tag_err
= 0;
2194 count
= lastfree
= freeseen
= 0;
2195 if (INT_GET(bf
[0].length
, ARCH_CONVERT
) == 0) {
2196 bf_err
+= INT_GET(bf
[0].offset
, ARCH_CONVERT
) != 0;
2199 if (INT_GET(bf
[1].length
, ARCH_CONVERT
) == 0) {
2200 bf_err
+= INT_GET(bf
[1].offset
, ARCH_CONVERT
) != 0;
2203 if (INT_GET(bf
[2].length
, ARCH_CONVERT
) == 0) {
2204 bf_err
+= INT_GET(bf
[2].offset
, ARCH_CONVERT
) != 0;
2207 bf_err
+= INT_GET(bf
[0].length
, ARCH_CONVERT
) < INT_GET(bf
[1].length
, ARCH_CONVERT
);
2208 bf_err
+= INT_GET(bf
[1].length
, ARCH_CONVERT
) < INT_GET(bf
[2].length
, ARCH_CONVERT
);
2210 freetab
= *freetabp
;
2211 if (freetab
->naents
<= db
) {
2212 *freetabp
= freetab
=
2213 realloc(freetab
, FREETAB_SIZE(db
+ 1));
2214 for (i
= freetab
->naents
; i
< db
; i
++)
2215 freetab
->ents
[i
] = NULLDATAOFF
;
2216 freetab
->naents
= db
+ 1;
2218 if (freetab
->nents
< db
+ 1)
2219 freetab
->nents
= db
+ 1;
2220 freetab
->ents
[db
] = INT_GET(bf
[0].length
, ARCH_CONVERT
);
2222 while (ptr
< endptr
) {
2223 dup
= (xfs_dir2_data_unused_t
*)ptr
;
2224 if (INT_GET(dup
->freetag
, ARCH_CONVERT
) == XFS_DIR2_DATA_FREE_TAG
) {
2225 lastfree_err
+= lastfree
!= 0;
2226 if ((INT_GET(dup
->length
, ARCH_CONVERT
) & (XFS_DIR2_DATA_ALIGN
- 1)) ||
2227 INT_GET(dup
->length
, ARCH_CONVERT
) == 0 ||
2228 (char *)(tagp
= XFS_DIR2_DATA_UNUSED_TAG_P_ARCH(dup
, ARCH_CONVERT
)) >=
2231 dbprintf("dir %lld block %d bad free "
2239 tag_err
+= INT_GET(*tagp
, ARCH_CONVERT
) != (char *)dup
- (char *)data
;
2240 dfp
= process_data_dir_v2_freefind(data
, dup
);
2242 i
= (int)(dfp
- bf
);
2243 bf_err
+= (freeseen
& (1 << i
)) != 0;
2246 bf_err
+= INT_GET(dup
->length
, ARCH_CONVERT
) > INT_GET(bf
[2].length
, ARCH_CONVERT
);
2247 ptr
+= INT_GET(dup
->length
, ARCH_CONVERT
);
2251 dep
= (xfs_dir2_data_entry_t
*)dup
;
2252 if (dep
->namelen
== 0) {
2254 dbprintf("dir %lld block %d zero length entry "
2257 (int)((char *)dep
- (char *)data
));
2260 tagp
= XFS_DIR2_DATA_ENTRY_TAG_P(dep
);
2261 if ((char *)tagp
>= endptr
) {
2263 dbprintf("dir %lld block %d bad entry at %d\n",
2265 (int)((char *)dep
- (char *)data
));
2269 tag_err
+= INT_GET(*tagp
, ARCH_CONVERT
) != (char *)dep
- (char *)data
;
2270 addr
= XFS_DIR2_DB_OFF_TO_DATAPTR(mp
, db
,
2271 (char *)dep
- (char *)data
);
2272 hash
= libxfs_da_hashname((char *)dep
->name
, dep
->namelen
);
2273 dir_hash_add(hash
, addr
);
2274 ptr
+= XFS_DIR2_DATA_ENTSIZE(dep
->namelen
);
2277 lino
= INT_GET(dep
->inumber
, ARCH_CONVERT
);
2278 cid
= find_inode(lino
, 1);
2280 dbprintf("dir %lld block %d entry %*.*s %lld\n",
2281 id
->ino
, dabno
, dep
->namelen
, dep
->namelen
,
2287 dbprintf("dir %lld block %d entry %*.*s bad "
2288 "inode number %lld\n",
2289 id
->ino
, dabno
, dep
->namelen
,
2290 dep
->namelen
, dep
->name
, lino
);
2293 if (dep
->namelen
== 2 && dep
->name
[0] == '.' &&
2294 dep
->name
[1] == '.') {
2297 dbprintf("multiple .. entries in dir "
2298 "%lld (%lld, %lld)\n",
2299 id
->ino
, parent
, lino
);
2302 parent
= cid
? lino
: NULLFSINO
;
2304 } else if (dep
->namelen
!= 1 || dep
->name
[0] != '.') {
2308 addname_inode(cid
, (char *)dep
->name
,
2312 if (lino
!= id
->ino
) {
2314 dbprintf("dir %lld entry . inode "
2315 "number mismatch (%lld)\n",
2322 if (INT_GET(data
->hdr
.magic
, ARCH_CONVERT
) == XFS_DIR2_BLOCK_MAGIC
) {
2323 endptr
= (char *)data
+ mp
->m_dirblksize
;
2324 for (i
= stale
= 0; lep
&& i
< INT_GET(btp
->count
, ARCH_CONVERT
); i
++) {
2325 if ((char *)&lep
[i
] >= endptr
) {
2327 dbprintf("dir %lld block %d bad count "
2329 id
->ino
, dabno
, INT_GET(btp
->count
, ARCH_CONVERT
));
2333 if (INT_GET(lep
[i
].address
, ARCH_CONVERT
) == XFS_DIR2_NULL_DATAPTR
)
2335 else if (dir_hash_see(INT_GET(lep
[i
].hashval
, ARCH_CONVERT
), INT_GET(lep
[i
].address
, ARCH_CONVERT
))) {
2337 dbprintf("dir %lld block %d extra leaf "
2339 id
->ino
, dabno
, INT_GET(lep
[i
].hashval
, ARCH_CONVERT
),
2340 INT_GET(lep
[i
].address
, ARCH_CONVERT
));
2345 bf_err
+= freeseen
!= 7;
2348 dbprintf("dir %lld block %d bad bestfree data\n",
2352 if (INT_GET(data
->hdr
.magic
, ARCH_CONVERT
) == XFS_DIR2_BLOCK_MAGIC
&&
2353 count
!= INT_GET(btp
->count
, ARCH_CONVERT
) - INT_GET(btp
->stale
, ARCH_CONVERT
)) {
2355 dbprintf("dir %lld block %d bad block tail count %d "
2357 id
->ino
, dabno
, INT_GET(btp
->count
, ARCH_CONVERT
), INT_GET(btp
->stale
, ARCH_CONVERT
));
2360 if (INT_GET(data
->hdr
.magic
, ARCH_CONVERT
) == XFS_DIR2_BLOCK_MAGIC
&& stale
!= INT_GET(btp
->stale
, ARCH_CONVERT
)) {
2362 dbprintf("dir %lld block %d bad stale tail count %d\n",
2363 id
->ino
, dabno
, INT_GET(btp
->stale
, ARCH_CONVERT
));
2368 dbprintf("dir %lld block %d consecutive free entries\n",
2374 dbprintf("dir %lld block %d entry/unused tag "
2382 static xfs_dir2_data_free_t
*
2383 process_data_dir_v2_freefind(
2384 xfs_dir2_data_t
*data
,
2385 xfs_dir2_data_unused_t
*dup
)
2387 xfs_dir2_data_free_t
*dfp
;
2388 xfs_dir2_data_aoff_t off
;
2390 off
= (xfs_dir2_data_aoff_t
)((char *)dup
- (char *)data
);
2391 if (INT_GET(dup
->length
, ARCH_CONVERT
) < INT_GET(data
->hdr
.bestfree
[XFS_DIR2_DATA_FD_COUNT
- 1].length
, ARCH_CONVERT
))
2393 for (dfp
= &data
->hdr
.bestfree
[0];
2394 dfp
< &data
->hdr
.bestfree
[XFS_DIR2_DATA_FD_COUNT
];
2396 if (INT_GET(dfp
->offset
, ARCH_CONVERT
) == 0)
2398 if (INT_GET(dfp
->offset
, ARCH_CONVERT
) == off
)
2416 if (XFS_DIR_IS_V2(mp
)) {
2417 if (process_dir_v2(dip
, blkmap
, &dot
, &dotdot
, id
, &parent
))
2421 if (process_dir_v1(dip
, blkmap
, &dot
, &dotdot
, id
, &parent
))
2424 bno
= XFS_INO_TO_FSB(mp
, id
->ino
);
2426 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2427 dbprintf("no . entry for directory %lld\n", id
->ino
);
2431 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2432 dbprintf("no .. entry for directory %lld\n", id
->ino
);
2434 } else if (parent
== id
->ino
&& id
->ino
!= mp
->m_sb
.sb_rootino
) {
2435 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2436 dbprintf(". and .. same for non-root directory %lld\n",
2439 } else if (id
->ino
== mp
->m_sb
.sb_rootino
&& id
->ino
!= parent
) {
2440 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2441 dbprintf("root directory %lld has .. %lld\n", id
->ino
,
2444 } else if (parent
!= NULLFSINO
&& id
->ino
!= parent
)
2445 addparent_inode(id
, parent
);
2457 if (dip
->di_core
.di_size
<= XFS_DFORK_DSIZE_ARCH(dip
, mp
, ARCH_NOCONVERT
) &&
2458 dip
->di_core
.di_format
== XFS_DINODE_FMT_LOCAL
)
2460 process_shortform_dir_v1(dip
, dot
, dotdot
, id
);
2461 else if (dip
->di_core
.di_size
== XFS_LBSIZE(mp
) &&
2462 (dip
->di_core
.di_format
== XFS_DINODE_FMT_EXTENTS
||
2463 dip
->di_core
.di_format
== XFS_DINODE_FMT_BTREE
))
2464 *parent
= process_leaf_dir_v1(blkmap
, dot
, dotdot
, id
);
2465 else if (dip
->di_core
.di_size
>= XFS_LBSIZE(mp
) &&
2466 (dip
->di_core
.di_format
== XFS_DINODE_FMT_EXTENTS
||
2467 dip
->di_core
.di_format
== XFS_DINODE_FMT_BTREE
))
2468 *parent
= process_node_dir_v1(blkmap
, dot
, dotdot
, id
);
2470 dbprintf("bad size (%lld) or format (%d) for directory inode "
2472 dip
->di_core
.di_size
, (int)dip
->di_core
.di_format
,
2489 xfs_fileoff_t last
= 0;
2492 last
= blkmap_last_off(blkmap
);
2493 if (dip
->di_core
.di_size
<= XFS_DFORK_DSIZE_ARCH(dip
, mp
, ARCH_NOCONVERT
) &&
2494 dip
->di_core
.di_format
== XFS_DINODE_FMT_LOCAL
)
2495 *parent
= process_sf_dir_v2(dip
, dot
, dotdot
, id
);
2496 else if (last
== mp
->m_dirblkfsbs
&&
2497 (dip
->di_core
.di_format
== XFS_DINODE_FMT_EXTENTS
||
2498 dip
->di_core
.di_format
== XFS_DINODE_FMT_BTREE
))
2499 *parent
= process_block_dir_v2(blkmap
, dot
, dotdot
, id
);
2500 else if (last
>= mp
->m_dirleafblk
+ mp
->m_dirblkfsbs
&&
2501 (dip
->di_core
.di_format
== XFS_DINODE_FMT_EXTENTS
||
2502 dip
->di_core
.di_format
== XFS_DINODE_FMT_BTREE
))
2503 *parent
= process_leaf_node_dir_v2(blkmap
, dot
, dotdot
, id
,
2504 dip
->di_core
.di_size
);
2506 dbprintf("bad size (%lld) or format (%d) for directory inode "
2508 dip
->di_core
.di_size
, (int)dip
->di_core
.di_format
,
2522 xfs_drfsbno_t
*totd
,
2523 xfs_drfsbno_t
*toti
,
2528 xfs_bmbt_rec_32_t
*rp
;
2530 rp
= (xfs_bmbt_rec_32_t
*)XFS_DFORK_PTR_ARCH(dip
, whichfork
, ARCH_NOCONVERT
);
2531 *nex
= XFS_DFORK_NEXTENTS_ARCH(dip
, whichfork
, ARCH_NOCONVERT
);
2534 XFS_DFORK_SIZE_ARCH(dip
, mp
, whichfork
, ARCH_NOCONVERT
) / sizeof(xfs_bmbt_rec_32_t
)) {
2535 if (!sflag
|| id
->ilist
)
2536 dbprintf("bad number of extents %d for inode %lld\n",
2541 process_bmbt_reclist(rp
, *nex
, type
, id
, totd
, blkmapp
);
2552 xfs_fsblock_t bno
= 0;
2553 xfs_dinode_core_t tdic
;
2554 xfs_dinode_core_t
*dic
;
2555 inodata_t
*id
= NULL
;
2557 xfs_extnum_t nextents
= 0;
2560 xfs_drfsbno_t totblocks
;
2561 xfs_drfsbno_t totdblocks
= 0;
2562 xfs_drfsbno_t totiblocks
= 0;
2564 xfs_extnum_t anextents
= 0;
2565 xfs_drfsbno_t atotdblocks
= 0;
2566 xfs_drfsbno_t atotiblocks
= 0;
2570 static char okfmts
[] = {
2571 0, /* type 0 unused */
2572 1 << XFS_DINODE_FMT_DEV
, /* FIFO */
2573 1 << XFS_DINODE_FMT_DEV
, /* CHR */
2574 0, /* type 3 unused */
2575 (1 << XFS_DINODE_FMT_LOCAL
) |
2576 (1 << XFS_DINODE_FMT_EXTENTS
) |
2577 (1 << XFS_DINODE_FMT_BTREE
), /* DIR */
2578 0, /* type 5 unused */
2579 1 << XFS_DINODE_FMT_DEV
, /* BLK */
2580 0, /* type 7 unused */
2581 (1 << XFS_DINODE_FMT_EXTENTS
) |
2582 (1 << XFS_DINODE_FMT_BTREE
), /* REG */
2583 0, /* type 9 unused */
2584 (1 << XFS_DINODE_FMT_LOCAL
) |
2585 (1 << XFS_DINODE_FMT_EXTENTS
), /* LNK */
2586 0, /* type 11 unused */
2587 1 << XFS_DINODE_FMT_DEV
, /* SOCK */
2588 0, /* type 13 unused */
2589 1 << XFS_DINODE_FMT_UUID
, /* MNT */
2590 0 /* type 15 unused */
2592 static char *fmtnames
[] = {
2593 "dev", "local", "extents", "btree", "uuid"
2596 /* convert the core, then copy it back into the inode */
2597 libxfs_xlate_dinode_core((xfs_caddr_t
)&dip
->di_core
, &tdic
, 1,
2599 memcpy(&dip
->di_core
, &tdic
, sizeof(xfs_dinode_core_t
));
2602 ino
= XFS_AGINO_TO_INO(mp
, INT_GET(agf
->agf_seqno
, ARCH_CONVERT
), agino
);
2604 id
= find_inode(ino
, 1);
2605 bno
= XFS_INO_TO_FSB(mp
, ino
);
2608 if (dic
->di_magic
!= XFS_DINODE_MAGIC
) {
2609 if (!sflag
|| isfree
|| id
->ilist
|| CHECK_BLIST(bno
))
2610 dbprintf("bad magic number %#x for inode %lld\n",
2611 dic
->di_magic
, ino
);
2615 if (!XFS_DINODE_GOOD_VERSION(dic
->di_version
)) {
2616 if (!sflag
|| isfree
|| id
->ilist
|| CHECK_BLIST(bno
))
2617 dbprintf("bad version number %#x for inode %lld\n",
2618 dic
->di_version
, ino
);
2623 if (dic
->di_nblocks
!= 0) {
2624 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2625 dbprintf("bad nblocks %lld for free inode "
2627 dic
->di_nblocks
, ino
);
2630 if (dic
->di_version
== XFS_DINODE_VERSION_1
)
2631 nlink
= dic
->di_onlink
;
2633 nlink
= dic
->di_nlink
;
2635 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2636 dbprintf("bad nlink %d for free inode %lld\n",
2640 if (dic
->di_mode
!= 0) {
2641 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2642 dbprintf("bad mode %#o for free inode %lld\n",
2649 * di_mode is a 16-bit uint so no need to check the < 0 case
2651 if ((((dic
->di_mode
& IFMT
) >> 12) > 15) ||
2652 (!(okfmts
[(dic
->di_mode
& IFMT
) >> 12] & (1 << dic
->di_format
)))) {
2653 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2654 dbprintf("bad format %d for inode %lld type %#o\n",
2655 dic
->di_format
, id
->ino
, dic
->di_mode
& IFMT
);
2659 if ((unsigned int)XFS_DFORK_ASIZE_ARCH(dip
, mp
, ARCH_NOCONVERT
) >= XFS_LITINO(mp
)) {
2660 if (!sflag
|| id
->ilist
)
2661 dbprintf("bad fork offset %d for inode %lld\n",
2662 dic
->di_forkoff
, id
->ino
);
2666 if ((unsigned int)dic
->di_aformat
> XFS_DINODE_FMT_BTREE
) {
2667 if (!sflag
|| id
->ilist
)
2668 dbprintf("bad attribute format %d for inode %lld\n",
2669 dic
->di_aformat
, id
->ino
);
2673 if (verbose
|| id
->ilist
|| CHECK_BLIST(bno
))
2674 dbprintf("inode %lld mode %#o fmt %s "
2676 "nex %d anex %d nblk %lld sz %lld%s%s\n",
2677 id
->ino
, dic
->di_mode
, fmtnames
[(int)dic
->di_format
],
2678 fmtnames
[(int)dic
->di_aformat
],
2681 dic
->di_nblocks
, dic
->di_size
,
2682 dic
->di_flags
& XFS_DIFLAG_REALTIME
? " rt" : "",
2683 dic
->di_flags
& XFS_DIFLAG_PREALLOC
? " pre" : ""
2686 switch (dic
->di_mode
& IFMT
) {
2689 if (dic
->di_format
== XFS_DINODE_FMT_LOCAL
)
2691 blkmap
= blkmap_alloc(dic
->di_nextents
);
2694 if (dic
->di_flags
& XFS_DIFLAG_REALTIME
)
2696 else if (id
->ino
== mp
->m_sb
.sb_rbmino
) {
2697 type
= DBM_RTBITMAP
;
2698 blkmap
= blkmap_alloc(dic
->di_nextents
);
2700 } else if (id
->ino
== mp
->m_sb
.sb_rsumino
) {
2702 blkmap
= blkmap_alloc(dic
->di_nextents
);
2705 else if (id
->ino
== mp
->m_sb
.sb_uquotino
||
2706 id
->ino
== mp
->m_sb
.sb_gquotino
) {
2708 blkmap
= blkmap_alloc(dic
->di_nextents
);
2713 if (dic
->di_mode
& (ISUID
| ISGID
))
2724 if (dic
->di_version
== XFS_DINODE_VERSION_1
)
2725 setlink_inode(id
, dic
->di_onlink
, type
== DBM_DIR
, security
);
2727 sbversion
|= XFS_SB_VERSION_NLINKBIT
;
2728 setlink_inode(id
, dic
->di_nlink
, type
== DBM_DIR
, security
);
2730 switch (dic
->di_format
) {
2731 case XFS_DINODE_FMT_LOCAL
:
2732 process_lclinode(id
, dip
, type
, &totdblocks
, &totiblocks
,
2733 &nextents
, &blkmap
, XFS_DATA_FORK
);
2735 case XFS_DINODE_FMT_EXTENTS
:
2736 process_exinode(id
, dip
, type
, &totdblocks
, &totiblocks
,
2737 &nextents
, &blkmap
, XFS_DATA_FORK
);
2739 case XFS_DINODE_FMT_BTREE
:
2740 process_btinode(id
, dip
, type
, &totdblocks
, &totiblocks
,
2741 &nextents
, &blkmap
, XFS_DATA_FORK
);
2744 if (XFS_DFORK_Q_ARCH(dip
, ARCH_NOCONVERT
)) {
2745 sbversion
|= XFS_SB_VERSION_ATTRBIT
;
2746 switch (dic
->di_aformat
) {
2747 case XFS_DINODE_FMT_LOCAL
:
2748 process_lclinode(id
, dip
, DBM_ATTR
, &atotdblocks
,
2749 &atotiblocks
, &anextents
, NULL
, XFS_ATTR_FORK
);
2751 case XFS_DINODE_FMT_EXTENTS
:
2752 process_exinode(id
, dip
, DBM_ATTR
, &atotdblocks
,
2753 &atotiblocks
, &anextents
, NULL
, XFS_ATTR_FORK
);
2755 case XFS_DINODE_FMT_BTREE
:
2756 process_btinode(id
, dip
, DBM_ATTR
, &atotdblocks
,
2757 &atotiblocks
, &anextents
, NULL
, XFS_ATTR_FORK
);
2769 bc
= totdblocks
+ totiblocks
+
2770 atotdblocks
+ atotiblocks
;
2774 bc
= totiblocks
+ atotdblocks
+ atotiblocks
;
2782 quota_add(dic
->di_gid
, dic
->di_uid
, 0, bc
, ic
, rc
);
2784 totblocks
= totdblocks
+ totiblocks
+ atotdblocks
+ atotiblocks
;
2785 if (totblocks
!= dic
->di_nblocks
) {
2786 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2787 dbprintf("bad nblocks %lld for inode %lld, counted "
2789 dic
->di_nblocks
, id
->ino
, totblocks
);
2792 if (nextents
!= dic
->di_nextents
) {
2793 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2794 dbprintf("bad nextents %d for inode %lld, counted %d\n",
2795 dic
->di_nextents
, id
->ino
, nextents
);
2798 if (anextents
!= dic
->di_anextents
) {
2799 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2800 dbprintf("bad anextents %d for inode %lld, counted "
2802 dic
->di_anextents
, id
->ino
, anextents
);
2805 if (type
== DBM_DIR
)
2806 process_dir(dip
, blkmap
, id
);
2807 else if (type
== DBM_RTBITMAP
)
2808 process_rtbitmap(blkmap
);
2809 else if (type
== DBM_RTSUM
)
2810 process_rtsummary(blkmap
);
2812 * If the CHKD flag is not set, this can legitimately contain garbage;
2813 * xfs_repair may have cleared that bit.
2815 else if (type
== DBM_QUOTA
) {
2816 if (id
->ino
== mp
->m_sb
.sb_uquotino
&&
2817 (mp
->m_sb
.sb_qflags
& XFS_UQUOTA_ACCT
) &&
2818 (mp
->m_sb
.sb_qflags
& XFS_UQUOTA_CHKD
))
2819 process_quota(0, id
, blkmap
);
2820 else if (id
->ino
== mp
->m_sb
.sb_gquotino
&&
2821 (mp
->m_sb
.sb_qflags
& XFS_GQUOTA_ACCT
) &&
2822 (mp
->m_sb
.sb_qflags
& XFS_GQUOTA_CHKD
))
2823 process_quota(1, id
, blkmap
);
2826 blkmap_free(blkmap
);
2835 xfs_drfsbno_t
*totd
,
2836 xfs_drfsbno_t
*toti
,
2841 xfs_attr_shortform_t
*asf
;
2843 xfs_dinode_core_t
*dic
;
2845 dic
= &dip
->di_core
;
2846 bno
= XFS_INO_TO_FSB(mp
, id
->ino
);
2847 if (whichfork
== XFS_DATA_FORK
&&
2848 dic
->di_size
> XFS_DFORK_DSIZE_ARCH(dip
, mp
, ARCH_NOCONVERT
)) {
2849 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2850 dbprintf("local inode %lld data is too large (size "
2852 id
->ino
, dic
->di_size
);
2855 else if (whichfork
== XFS_ATTR_FORK
) {
2856 asf
= (xfs_attr_shortform_t
*)XFS_DFORK_PTR_ARCH(dip
, whichfork
, ARCH_NOCONVERT
);
2857 if (INT_GET(asf
->hdr
.totsize
, ARCH_CONVERT
) > XFS_DFORK_ASIZE_ARCH(dip
, mp
, ARCH_NOCONVERT
)) {
2858 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2859 dbprintf("local inode %lld attr is too large "
2861 id
->ino
, INT_GET(asf
->hdr
.totsize
, ARCH_CONVERT
));
2868 process_leaf_dir_v1(
2877 bno
= blkmap_get(blkmap
, 0);
2878 if (bno
== NULLFSBLOCK
) {
2879 if (!sflag
|| id
->ilist
)
2880 dbprintf("block 0 for directory inode %lld is "
2887 set_cur(&typtab
[TYP_DIR
], XFS_FSB_TO_DADDR(mp
, bno
), blkbb
, DB_RING_IGN
,
2889 if (iocur_top
->data
== NULL
) {
2890 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2891 dbprintf("can't read block 0 for directory inode "
2897 parent
= process_leaf_dir_v1_int(dot
, dotdot
, id
);
2903 process_leaf_dir_v1_int(
2910 xfs_dir_leaf_entry_t
*entry
;
2912 xfs_dir_leafblock_t
*leaf
;
2914 xfs_dir_leaf_name_t
*namest
;
2915 xfs_ino_t parent
= 0;
2918 bno
= XFS_DADDR_TO_FSB(mp
, iocur_top
->bb
);
2919 v
= verbose
|| id
->ilist
|| CHECK_BLIST(bno
);
2920 leaf
= iocur_top
->data
;
2921 if (INT_GET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
) != XFS_DIR_LEAF_MAGIC
) {
2922 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2923 dbprintf("bad directory leaf magic # %#x for dir ino "
2925 INT_GET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
), id
->ino
);
2929 entry
= &leaf
->entries
[0];
2930 for (i
= 0; i
< INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
); entry
++, i
++) {
2931 namest
= XFS_DIR_LEAF_NAMESTRUCT(leaf
, INT_GET(entry
->nameidx
, ARCH_CONVERT
));
2932 lino
=DIRINO_GET_ARCH(&namest
->inumber
, ARCH_CONVERT
);
2933 cid
= find_inode(lino
, 1);
2935 dbprintf("dir %lld entry %*.*s %lld\n", id
->ino
,
2936 entry
->namelen
, entry
->namelen
, namest
->name
,
2942 dbprintf("dir %lld entry %*.*s bad inode "
2944 id
->ino
, entry
->namelen
, entry
->namelen
,
2945 namest
->name
, lino
);
2948 if (entry
->namelen
== 2 && namest
->name
[0] == '.' &&
2949 namest
->name
[1] == '.') {
2951 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2952 dbprintf("multiple .. entries in dir "
2953 "%lld (%lld, %lld)\n",
2954 id
->ino
, parent
, lino
);
2957 parent
= cid
? lino
: NULLFSINO
;
2959 } else if (entry
->namelen
!= 1 || namest
->name
[0] != '.') {
2963 addname_inode(cid
, (char *)namest
->name
,
2967 if (lino
!= id
->ino
) {
2969 dbprintf("dir %lld entry . inode "
2970 "number mismatch (%lld)\n",
2981 process_leaf_node_dir_v2(
2986 xfs_fsize_t dirsize
)
3002 v2
= verbose
|| id
->ilist
;
3005 freetab
= malloc(FREETAB_SIZE(dirsize
/ mp
->m_dirblksize
));
3006 freetab
->naents
= (int)(dirsize
/ mp
->m_dirblksize
);
3008 for (i
= 0; i
< freetab
->naents
; i
++)
3009 freetab
->ents
[i
] = NULLDATAOFF
;
3011 while ((dbno
= blkmap_next_off(blkmap
, dbno
, &t
)) != NULLFILEOFF
) {
3012 nex
= blkmap_getn(blkmap
, dbno
, mp
->m_dirblkfsbs
, &bmp
);
3014 for (v
= v2
, x
= 0; !v
&& x
< nex
; x
++) {
3015 for (b
= bmp
[x
].startblock
;
3016 !v
&& b
< bmp
[x
].startblock
+ bmp
[x
].blockcount
;
3021 dbprintf("dir inode %lld block %u=%llu\n", id
->ino
,
3023 (xfs_dfsbno_t
)bmp
->startblock
);
3026 make_bbmap(&bbmap
, nex
, bmp
);
3027 set_cur(&typtab
[TYP_DIR
], XFS_FSB_TO_DADDR(mp
, bmp
->startblock
),
3028 mp
->m_dirblkfsbs
* blkbb
, DB_RING_IGN
,
3029 nex
> 1 ? &bbmap
: NULL
);
3031 if (iocur_top
->data
== NULL
) {
3033 dbprintf("can't read block %u for directory "
3035 (__uint32_t
)dbno
, id
->ino
);
3038 dbno
+= mp
->m_dirblkfsbs
- 1;
3041 if (dbno
< mp
->m_dirleafblk
) {
3042 lino
= process_data_dir_v2(dot
, dotdot
, id
, v
,
3043 (xfs_dablk_t
)dbno
, &freetab
);
3047 dbprintf("multiple .. entries "
3054 } else if (dbno
< mp
->m_dirfreeblk
) {
3055 process_leaf_node_dir_v2_int(id
, v
, (xfs_dablk_t
)dbno
,
3058 process_leaf_node_dir_v2_free(id
, v
, (xfs_dablk_t
)dbno
,
3062 dbno
+= mp
->m_dirblkfsbs
- 1;
3064 dir_hash_check(id
, v
);
3066 for (i
= 0; i
< freetab
->nents
; i
++) {
3067 if (freetab
->ents
[i
] != NULLDATAOFF
) {
3069 dbprintf("missing free index for data block %d "
3070 "in dir ino %lld\n",
3071 XFS_DIR2_DB_TO_DA(mp
, i
), id
->ino
);
3080 process_leaf_node_dir_v2_free(
3086 xfs_dir2_data_off_t ent
;
3087 xfs_dir2_free_t
*free
;
3092 free
= iocur_top
->data
;
3093 if (INT_GET(free
->hdr
.magic
, ARCH_CONVERT
) != XFS_DIR2_FREE_MAGIC
) {
3095 dbprintf("bad free block magic # %#x for dir ino %lld "
3097 INT_GET(free
->hdr
.magic
, ARCH_CONVERT
), id
->ino
, dabno
);
3101 maxent
= XFS_DIR2_MAX_FREE_BESTS(mp
);
3102 if (INT_GET(free
->hdr
.firstdb
, ARCH_CONVERT
) !=
3103 XFS_DIR2_DA_TO_DB(mp
, dabno
- mp
->m_dirfreeblk
) * maxent
) {
3105 dbprintf("bad free block firstdb %d for dir ino %lld "
3107 INT_GET(free
->hdr
.firstdb
, ARCH_CONVERT
), id
->ino
, dabno
);
3111 if (INT_GET(free
->hdr
.nvalid
, ARCH_CONVERT
) > maxent
|| INT_GET(free
->hdr
.nvalid
, ARCH_CONVERT
) < 0 ||
3112 INT_GET(free
->hdr
.nused
, ARCH_CONVERT
) > maxent
|| INT_GET(free
->hdr
.nused
, ARCH_CONVERT
) < 0 ||
3113 INT_GET(free
->hdr
.nused
, ARCH_CONVERT
) > INT_GET(free
->hdr
.nvalid
, ARCH_CONVERT
)) {
3115 dbprintf("bad free block nvalid/nused %d/%d for dir "
3116 "ino %lld block %d\n",
3117 INT_GET(free
->hdr
.nvalid
, ARCH_CONVERT
), INT_GET(free
->hdr
.nused
, ARCH_CONVERT
), id
->ino
,
3122 for (used
= i
= 0; i
< INT_GET(free
->hdr
.nvalid
, ARCH_CONVERT
); i
++) {
3123 if (freetab
->nents
<= INT_GET(free
->hdr
.firstdb
, ARCH_CONVERT
) + i
)
3126 ent
= freetab
->ents
[INT_GET(free
->hdr
.firstdb
, ARCH_CONVERT
) + i
];
3127 if (ent
!= INT_GET(free
->bests
[i
], ARCH_CONVERT
)) {
3129 dbprintf("bad free block ent %d is %d should "
3130 "be %d for dir ino %lld block %d\n",
3131 i
, INT_GET(free
->bests
[i
], ARCH_CONVERT
), ent
, id
->ino
, dabno
);
3134 if (INT_GET(free
->bests
[i
], ARCH_CONVERT
) != NULLDATAOFF
)
3136 if (ent
!= NULLDATAOFF
)
3137 freetab
->ents
[INT_GET(free
->hdr
.firstdb
, ARCH_CONVERT
) + i
] = NULLDATAOFF
;
3139 if (used
!= INT_GET(free
->hdr
.nused
, ARCH_CONVERT
)) {
3141 dbprintf("bad free block nused %d should be %d for dir "
3142 "ino %lld block %d\n",
3143 INT_GET(free
->hdr
.nused
, ARCH_CONVERT
), used
, id
->ino
, dabno
);
3149 process_leaf_node_dir_v2_int(
3156 xfs_dir2_data_off_t
*lbp
;
3157 xfs_dir2_leaf_t
*leaf
;
3158 xfs_dir2_leaf_entry_t
*lep
;
3159 xfs_dir2_leaf_tail_t
*ltp
;
3160 xfs_da_intnode_t
*node
;
3163 leaf
= iocur_top
->data
;
3164 switch (INT_GET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
)) {
3165 case XFS_DIR2_LEAF1_MAGIC
:
3166 if (INT_GET(leaf
->hdr
.info
.forw
, ARCH_CONVERT
) || INT_GET(leaf
->hdr
.info
.back
, ARCH_CONVERT
)) {
3168 dbprintf("bad leaf block forw/back pointers "
3169 "%d/%d for dir ino %lld block %d\n",
3170 INT_GET(leaf
->hdr
.info
.forw
, ARCH_CONVERT
),
3171 INT_GET(leaf
->hdr
.info
.back
, ARCH_CONVERT
), id
->ino
, dabno
);
3174 if (dabno
!= mp
->m_dirleafblk
) {
3176 dbprintf("single leaf block for dir ino %lld "
3177 "block %d should be at block %d\n",
3179 (xfs_dablk_t
)mp
->m_dirleafblk
);
3182 ltp
= XFS_DIR2_LEAF_TAIL_P(mp
, leaf
);
3183 lbp
= XFS_DIR2_LEAF_BESTS_P_ARCH(ltp
, ARCH_CONVERT
);
3184 for (i
= 0; i
< INT_GET(ltp
->bestcount
, ARCH_CONVERT
); i
++) {
3185 if (freetab
->nents
<= i
|| freetab
->ents
[i
] != INT_GET(lbp
[i
], ARCH_CONVERT
)) {
3187 dbprintf("bestfree %d for dir ino %lld "
3188 "block %d doesn't match table "
3190 freetab
->nents
<= i
?
3194 XFS_DIR2_DB_TO_DA(mp
, i
),
3195 INT_GET(lbp
[i
], ARCH_CONVERT
));
3197 if (freetab
->nents
> i
)
3198 freetab
->ents
[i
] = NULLDATAOFF
;
3201 case XFS_DIR2_LEAFN_MAGIC
:
3202 /* if it's at the root location then we can check the
3203 * pointers are null XXX */
3205 case XFS_DA_NODE_MAGIC
:
3206 node
= iocur_top
->data
;
3207 if (INT_GET(node
->hdr
.level
, ARCH_CONVERT
) < 1 ||
3208 INT_GET(node
->hdr
.level
, ARCH_CONVERT
) > XFS_DA_NODE_MAXDEPTH
) {
3210 dbprintf("bad node block level %d for dir ino "
3212 INT_GET(node
->hdr
.level
, ARCH_CONVERT
), id
->ino
, dabno
);
3218 dbprintf("bad directory data magic # %#x for dir ino "
3220 INT_GET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
), id
->ino
, dabno
);
3225 for (i
= stale
= 0; i
< INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
); i
++) {
3226 if (INT_GET(lep
[i
].address
, ARCH_CONVERT
) == XFS_DIR2_NULL_DATAPTR
)
3228 else if (dir_hash_see(INT_GET(lep
[i
].hashval
, ARCH_CONVERT
), INT_GET(lep
[i
].address
, ARCH_CONVERT
))) {
3230 dbprintf("dir %lld block %d extra leaf entry "
3232 id
->ino
, dabno
, INT_GET(lep
[i
].hashval
, ARCH_CONVERT
),
3233 INT_GET(lep
[i
].address
, ARCH_CONVERT
));
3237 if (stale
!= INT_GET(leaf
->hdr
.stale
, ARCH_CONVERT
)) {
3239 dbprintf("dir %lld block %d stale mismatch "
3241 id
->ino
, dabno
, stale
,
3242 INT_GET(leaf
->hdr
.stale
, ARCH_CONVERT
));
3248 process_node_dir_v1(
3257 xfs_da_intnode_t
*node
;
3263 v
= verbose
|| id
->ilist
;
3266 while ((dbno
= blkmap_next_off(blkmap
, dbno
, &t
)) != NULLFILEOFF
) {
3267 bno
= blkmap_get(blkmap
, dbno
);
3268 v2
= bno
!= NULLFSBLOCK
&& CHECK_BLIST(bno
);
3269 if (bno
== NULLFSBLOCK
&& dbno
== 0) {
3271 dbprintf("can't read root block for directory "
3277 dbprintf("dir inode %lld block %u=%llu\n", id
->ino
,
3278 (__uint32_t
)dbno
, (xfs_dfsbno_t
)bno
);
3279 if (bno
== NULLFSBLOCK
)
3282 set_cur(&typtab
[TYP_DIR
], XFS_FSB_TO_DADDR(mp
, bno
), blkbb
,
3284 if ((node
= iocur_top
->data
) == NULL
) {
3285 if (!sflag
|| v
|| v2
)
3286 dbprintf("can't read block %u for directory "
3288 (__uint32_t
)dbno
, id
->ino
);
3293 if (INT_GET(node
->hdr
.info
.magic
, ARCH_CONVERT
) == XFS_DA_NODE_MAGIC
)
3295 if (INT_GET(node
->hdr
.info
.magic
, ARCH_CONVERT
) == XFS_DIR_NODE_MAGIC
)
3301 lino
= process_leaf_dir_v1_int(dot
, dotdot
, id
);
3304 if (!sflag
|| v
|| v2
)
3305 dbprintf("multiple .. entries in dir "
3335 perblock
= (int)(mp
->m_sb
.sb_blocksize
/ sizeof(*dqb
));
3336 s
= isgrp
? "group" : "user";
3337 exp_flags
= isgrp
? XFS_DQ_GROUP
: XFS_DQ_USER
;
3340 while ((qbno
= blkmap_next_off(blkmap
, qbno
, &t
)) !=
3342 bno
= blkmap_get(blkmap
, qbno
);
3343 dqid
= (xfs_dqid_t
)qbno
* perblock
;
3344 cb
= CHECK_BLIST(bno
);
3345 scicb
= !sflag
|| id
->ilist
|| cb
;
3347 set_cur(&typtab
[TYP_DQBLK
], XFS_FSB_TO_DADDR(mp
, bno
), blkbb
,
3349 if ((dqb
= iocur_top
->data
) == NULL
) {
3352 dbprintf("can't read block %lld for %s quota "
3353 "inode (fsblock %lld)\n",
3354 (xfs_dfiloff_t
)qbno
, s
,
3359 for (i
= 0; i
< perblock
; i
++, dqid
++, dqb
++) {
3360 if (verbose
|| id
->ilist
|| cb
)
3361 dbprintf("%s dqblk %lld entry %d id %d bc "
3362 "%lld ic %lld rc %lld\n",
3363 s
, (xfs_dfiloff_t
)qbno
, i
, dqid
,
3364 INT_GET(dqb
->dd_diskdq
.d_bcount
, ARCH_CONVERT
),
3365 INT_GET(dqb
->dd_diskdq
.d_icount
, ARCH_CONVERT
),
3366 INT_GET(dqb
->dd_diskdq
.d_rtbcount
, ARCH_CONVERT
));
3367 if (INT_GET(dqb
->dd_diskdq
.d_magic
, ARCH_CONVERT
) != XFS_DQUOT_MAGIC
) {
3369 dbprintf("bad magic number %#x for %s "
3370 "dqblk %lld entry %d id %d\n",
3371 INT_GET(dqb
->dd_diskdq
.d_magic
, ARCH_CONVERT
), s
,
3372 (xfs_dfiloff_t
)qbno
, i
, dqid
);
3376 if (INT_GET(dqb
->dd_diskdq
.d_version
, ARCH_CONVERT
) != XFS_DQUOT_VERSION
) {
3378 dbprintf("bad version number %#x for "
3379 "%s dqblk %lld entry %d id "
3381 INT_GET(dqb
->dd_diskdq
.d_version
, ARCH_CONVERT
), s
,
3382 (xfs_dfiloff_t
)qbno
, i
, dqid
);
3386 if (INT_GET(dqb
->dd_diskdq
.d_flags
, ARCH_CONVERT
) != exp_flags
) {
3388 dbprintf("bad flags %#x for %s dqblk "
3389 "%lld entry %d id %d\n",
3390 INT_GET(dqb
->dd_diskdq
.d_flags
, ARCH_CONVERT
), s
,
3391 (xfs_dfiloff_t
)qbno
, i
, dqid
);
3395 if (INT_GET(dqb
->dd_diskdq
.d_id
, ARCH_CONVERT
) != dqid
) {
3397 dbprintf("bad id %d for %s dqblk %lld "
3399 INT_GET(dqb
->dd_diskdq
.d_id
, ARCH_CONVERT
), s
,
3400 (xfs_dfiloff_t
)qbno
, i
, dqid
);
3404 quota_add(isgrp
? dqid
: -1, isgrp
? -1 : dqid
, 1,
3405 INT_GET(dqb
->dd_diskdq
.d_bcount
, ARCH_CONVERT
),
3406 INT_GET(dqb
->dd_diskdq
.d_icount
, ARCH_CONVERT
),
3407 INT_GET(dqb
->dd_diskdq
.d_rtbcount
, ARCH_CONVERT
));
3417 #define xfs_highbit64 libxfs_highbit64 /* for XFS_RTBLOCKLOG macro */
3420 xfs_fileoff_t bmbno
;
3427 xfs_drfsbno_t rtbno
;
3431 xfs_rtword_t
*words
;
3433 bitsperblock
= mp
->m_sb
.sb_blocksize
* NBBY
;
3434 bit
= extno
= prevbit
= start_bmbno
= start_bit
= 0;
3435 bmbno
= NULLFILEOFF
;
3436 while ((bmbno
= blkmap_next_off(blkmap
, bmbno
, &t
)) !=
3438 bno
= blkmap_get(blkmap
, bmbno
);
3439 if (bno
== NULLFSBLOCK
) {
3441 dbprintf("block %lld for rtbitmap inode is "
3443 (xfs_dfiloff_t
)bmbno
);
3448 set_cur(&typtab
[TYP_RTBITMAP
], XFS_FSB_TO_DADDR(mp
, bno
), blkbb
,
3450 if ((words
= iocur_top
->data
) == NULL
) {
3453 dbprintf("can't read block %lld for rtbitmap "
3455 (xfs_dfiloff_t
)bmbno
);
3460 bit
< bitsperblock
&& extno
< mp
->m_sb
.sb_rextents
;
3462 if (isset(words
, bit
)) {
3463 rtbno
= extno
* mp
->m_sb
.sb_rextsize
;
3464 set_rdbmap(rtbno
, mp
->m_sb
.sb_rextsize
,
3468 start_bmbno
= (int)bmbno
;
3472 } else if (prevbit
== 1) {
3473 len
= ((int)bmbno
- start_bmbno
) *
3474 bitsperblock
+ (bit
- start_bit
);
3475 log
= XFS_RTBLOCKLOG(len
);
3476 offs
= XFS_SUMOFFS(mp
, log
, start_bmbno
);
3482 if (extno
== mp
->m_sb
.sb_rextents
)
3486 len
= ((int)bmbno
- start_bmbno
) * bitsperblock
+
3488 log
= XFS_RTBLOCKLOG(len
);
3489 offs
= XFS_SUMOFFS(mp
, log
, start_bmbno
);
3500 xfs_fileoff_t sumbno
;
3503 sumbno
= NULLFILEOFF
;
3504 while ((sumbno
= blkmap_next_off(blkmap
, sumbno
, &t
)) !=
3506 bno
= blkmap_get(blkmap
, sumbno
);
3507 if (bno
== NULLFSBLOCK
) {
3509 dbprintf("block %lld for rtsummary inode is "
3511 (xfs_dfiloff_t
)sumbno
);
3516 set_cur(&typtab
[TYP_RTSUMMARY
], XFS_FSB_TO_DADDR(mp
, bno
),
3517 blkbb
, DB_RING_IGN
, NULL
);
3518 if ((bytes
= iocur_top
->data
) == NULL
) {
3520 dbprintf("can't read block %lld for rtsummary "
3522 (xfs_dfiloff_t
)sumbno
);
3526 memcpy((char *)sumfile
+ sumbno
* mp
->m_sb
.sb_blocksize
, bytes
,
3527 mp
->m_sb
.sb_blocksize
);
3545 xfs_dir2_sf_entry_t
*sfe
;
3548 sf
= &dip
->di_u
.di_dir2sf
;
3550 v
= verbose
|| id
->ilist
;
3552 dbprintf("dir %lld entry . %lld\n", id
->ino
, id
->ino
);
3554 sfe
= XFS_DIR2_SF_FIRSTENTRY(sf
);
3555 offset
= XFS_DIR2_DATA_FIRST_OFFSET
;
3556 for (i
= INT_GET(sf
->hdr
.count
, ARCH_CONVERT
) - 1, i8
= 0; i
>= 0; i
--) {
3557 if ((__psint_t
)sfe
+ XFS_DIR2_SF_ENTSIZE_BYENTRY(sf
, sfe
) -
3558 (__psint_t
)sf
> dip
->di_core
.di_size
) {
3560 dbprintf("dir %llu bad size in entry at %d\n",
3562 (int)((char *)sfe
- (char *)sf
));
3566 lino
= XFS_DIR2_SF_GET_INUMBER_ARCH(sf
, XFS_DIR2_SF_INUMBERP(sfe
), ARCH_CONVERT
);
3567 if (lino
> XFS_DIR2_MAX_SHORT_INUM
)
3569 cid
= find_inode(lino
, 1);
3572 dbprintf("dir %lld entry %*.*s bad inode "
3574 id
->ino
, sfe
->namelen
, sfe
->namelen
,
3581 addname_inode(cid
, (char *)sfe
->name
, sfe
->namelen
);
3584 dbprintf("dir %lld entry %*.*s offset %d %lld\n",
3585 id
->ino
, sfe
->namelen
, sfe
->namelen
, sfe
->name
,
3586 XFS_DIR2_SF_GET_OFFSET_ARCH(sfe
, ARCH_CONVERT
), lino
);
3587 if (XFS_DIR2_SF_GET_OFFSET_ARCH(sfe
, ARCH_CONVERT
) < offset
) {
3589 dbprintf("dir %lld entry %*.*s bad offset %d\n",
3590 id
->ino
, sfe
->namelen
, sfe
->namelen
,
3591 sfe
->name
, XFS_DIR2_SF_GET_OFFSET_ARCH(sfe
, ARCH_CONVERT
));
3595 XFS_DIR2_SF_GET_OFFSET_ARCH(sfe
, ARCH_CONVERT
) +
3596 XFS_DIR2_DATA_ENTSIZE(sfe
->namelen
);
3597 sfe
= XFS_DIR2_SF_NEXTENTRY(sf
, sfe
);
3599 if (i
< 0 && (__psint_t
)sfe
- (__psint_t
)sf
!= dip
->di_core
.di_size
) {
3601 dbprintf("dir %llu size is %lld, should be %u\n",
3602 id
->ino
, dip
->di_core
.di_size
,
3603 (uint
)((char *)sfe
- (char *)sf
));
3606 if (offset
+ (INT_GET(sf
->hdr
.count
, ARCH_CONVERT
) + 2) * sizeof(xfs_dir2_leaf_entry_t
) +
3607 sizeof(xfs_dir2_block_tail_t
) > mp
->m_dirblksize
) {
3609 dbprintf("dir %llu offsets too high\n", id
->ino
);
3612 lino
= XFS_DIR2_SF_GET_INUMBER_ARCH(sf
, &sf
->hdr
.parent
, ARCH_CONVERT
);
3613 if (lino
> XFS_DIR2_MAX_SHORT_INUM
)
3615 cid
= find_inode(lino
, 1);
3620 dbprintf("dir %lld entry .. bad inode number %lld\n",
3625 dbprintf("dir %lld entry .. %lld\n", id
->ino
, lino
);
3626 if (i8
!= sf
->hdr
.i8count
) {
3628 dbprintf("dir %lld i8count mismatch is %d should be "
3630 id
->ino
, sf
->hdr
.i8count
, i8
);
3634 return cid
? lino
: NULLFSINO
;
3638 process_shortform_dir_v1(
3647 xfs_dir_shortform_t
*sf
;
3648 xfs_dir_sf_entry_t
*sfe
;
3651 sf
= &dip
->di_u
.di_dirsf
;
3653 v
= verbose
|| id
->ilist
;
3655 dbprintf("dir %lld entry . %lld\n", id
->ino
, id
->ino
);
3658 for (i
= INT_GET(sf
->hdr
.count
, ARCH_CONVERT
) - 1; i
>= 0; i
--) {
3659 lino
= DIRINO_GET_ARCH(&sfe
->inumber
, ARCH_CONVERT
);
3660 cid
= find_inode(lino
, 1);
3663 dbprintf("dir %lld entry %*.*s bad inode "
3665 id
->ino
, sfe
->namelen
, sfe
->namelen
,
3672 addname_inode(cid
, (char *)sfe
->name
, sfe
->namelen
);
3675 dbprintf("dir %lld entry %*.*s %lld\n", id
->ino
,
3676 sfe
->namelen
, sfe
->namelen
, sfe
->name
, lino
);
3677 sfe
= XFS_DIR_SF_NEXTENTRY(sfe
);
3679 if ((__psint_t
)sfe
- (__psint_t
)sf
!= dip
->di_core
.di_size
)
3680 dbprintf("dir %llu size is %lld, should be %d\n",
3681 id
->ino
, dip
->di_core
.di_size
,
3682 (int)((char *)sfe
- (char *)sf
));
3683 lino
=DIRINO_GET_ARCH(&sf
->hdr
.parent
, ARCH_CONVERT
);
3684 cid
= find_inode(lino
, 1);
3689 dbprintf("dir %lld entry .. bad inode number %lld\n",
3694 dbprintf("dir %lld entry .. %lld\n", id
->ino
, lino
);
3696 return cid
? lino
: NULLFSINO
;
3708 if (qudo
&& usrid
!= -1)
3709 quota_add1(qudata
, usrid
, dq
, bc
, ic
, rc
);
3710 if (qgdo
&& grpid
!= -1)
3711 quota_add1(qgdata
, grpid
, dq
, bc
, ic
, rc
);
3727 qh
= (int)((__uint32_t
)id
% QDATA_HASH_SIZE
);
3731 qi
= dq
? &qe
->dq
: &qe
->count
;
3739 qe
= xmalloc(sizeof(*qe
));
3741 qi
= dq
? &qe
->dq
: &qe
->count
;
3745 qi
= dq
? &qe
->count
: &qe
->dq
;
3746 qi
->bc
= qi
->ic
= qi
->rc
= 0;
3760 for (i
= 0; i
< QDATA_HASH_SIZE
; i
++) {
3764 if (qp
->count
.bc
!= qp
->dq
.bc
||
3765 qp
->count
.ic
!= qp
->dq
.ic
||
3766 qp
->count
.rc
!= qp
->dq
.rc
) {
3768 dbprintf("%s quota id %d, have/exp",
3770 if (qp
->count
.bc
!= qp
->dq
.bc
)
3771 dbprintf(" bc %lld/%lld",
3774 if (qp
->count
.ic
!= qp
->dq
.ic
)
3775 dbprintf(" ic %lld/%lld",
3778 if (qp
->count
.rc
!= qp
->dq
.rc
)
3779 dbprintf(" rc %lld/%lld",
3796 qudo
= mp
->m_sb
.sb_uquotino
!= 0 &&
3797 mp
->m_sb
.sb_uquotino
!= NULLFSINO
&&
3798 (mp
->m_sb
.sb_qflags
& XFS_UQUOTA_ACCT
) &&
3799 (mp
->m_sb
.sb_qflags
& XFS_UQUOTA_CHKD
);
3800 qgdo
= mp
->m_sb
.sb_gquotino
!= 0 &&
3801 mp
->m_sb
.sb_gquotino
!= NULLFSINO
&&
3802 (mp
->m_sb
.sb_qflags
& XFS_GQUOTA_ACCT
) &&
3803 (mp
->m_sb
.sb_qflags
& XFS_GQUOTA_CHKD
);
3805 qudata
= xcalloc(QDATA_HASH_SIZE
, sizeof(qdata_t
*));
3807 qgdata
= xcalloc(QDATA_HASH_SIZE
, sizeof(qdata_t
*));
3812 xfs_agnumber_t agno
)
3820 agffreeblks
= agflongest
= 0;
3821 agicount
= agifreecount
= 0;
3823 set_cur(&typtab
[TYP_SB
],
3824 XFS_AG_DADDR(mp
, agno
, XFS_SB_DADDR
),
3825 XFS_FSS_TO_BB(mp
, 1), DB_RING_IGN
, NULL
);
3827 if (!iocur_top
->data
) {
3828 dbprintf("can't read superblock for ag %u\n", agno
);
3834 libxfs_xlate_sb(iocur_top
->data
, sb
, 1, ARCH_CONVERT
, XFS_SB_ALL_BITS
);
3836 if (sb
->sb_magicnum
!= XFS_SB_MAGIC
) {
3838 dbprintf("bad sb magic # %#x in ag %u\n",
3839 sb
->sb_magicnum
, agno
);
3842 if (!XFS_SB_GOOD_VERSION(sb
)) {
3844 dbprintf("bad sb version # %#x in ag %u\n",
3845 sb
->sb_versionnum
, agno
);
3849 if (agno
== 0 && sb
->sb_inprogress
!= 0) {
3851 dbprintf("mkfs not completed successfully\n");
3854 set_dbmap(agno
, XFS_SB_BLOCK(mp
), 1, DBM_SB
, agno
, XFS_SB_BLOCK(mp
));
3855 if (sb
->sb_logstart
&& XFS_FSB_TO_AGNO(mp
, sb
->sb_logstart
) == agno
)
3856 set_dbmap(agno
, XFS_FSB_TO_AGBNO(mp
, sb
->sb_logstart
),
3857 sb
->sb_logblocks
, DBM_LOG
, agno
, XFS_SB_BLOCK(mp
));
3859 set_cur(&typtab
[TYP_AGF
],
3860 XFS_AG_DADDR(mp
, agno
, XFS_AGF_DADDR(mp
)),
3861 XFS_FSS_TO_BB(mp
, 1), DB_RING_IGN
, NULL
);
3862 if ((agf
= iocur_top
->data
) == NULL
) {
3863 dbprintf("can't read agf block for ag %u\n", agno
);
3869 if (INT_GET(agf
->agf_magicnum
, ARCH_CONVERT
) != XFS_AGF_MAGIC
) {
3871 dbprintf("bad agf magic # %#x in ag %u\n",
3872 INT_GET(agf
->agf_magicnum
, ARCH_CONVERT
), agno
);
3875 if (!XFS_AGF_GOOD_VERSION(INT_GET(agf
->agf_versionnum
, ARCH_CONVERT
))) {
3877 dbprintf("bad agf version # %#x in ag %u\n",
3878 INT_GET(agf
->agf_versionnum
, ARCH_CONVERT
), agno
);
3881 if (XFS_SB_BLOCK(mp
) != XFS_AGF_BLOCK(mp
))
3882 set_dbmap(agno
, XFS_AGF_BLOCK(mp
), 1, DBM_AGF
, agno
,
3884 if (sb
->sb_agblocks
> INT_GET(agf
->agf_length
, ARCH_CONVERT
))
3885 set_dbmap(agno
, INT_GET(agf
->agf_length
, ARCH_CONVERT
),
3886 sb
->sb_agblocks
- INT_GET(agf
->agf_length
, ARCH_CONVERT
),
3887 DBM_MISSING
, agno
, XFS_SB_BLOCK(mp
));
3889 set_cur(&typtab
[TYP_AGI
],
3890 XFS_AG_DADDR(mp
, agno
, XFS_AGI_DADDR(mp
)),
3891 XFS_FSS_TO_BB(mp
, 1), DB_RING_IGN
, NULL
);
3892 if ((agi
= iocur_top
->data
) == NULL
) {
3893 dbprintf("can't read agi block for ag %u\n", agno
);
3900 if (INT_GET(agi
->agi_magicnum
, ARCH_CONVERT
) != XFS_AGI_MAGIC
) {
3902 dbprintf("bad agi magic # %#x in ag %u\n",
3903 INT_GET(agi
->agi_magicnum
, ARCH_CONVERT
), agno
);
3906 if (!XFS_AGI_GOOD_VERSION(INT_GET(agi
->agi_versionnum
, ARCH_CONVERT
))) {
3908 dbprintf("bad agi version # %#x in ag %u\n",
3909 INT_GET(agi
->agi_versionnum
, ARCH_CONVERT
), agno
);
3912 if (XFS_SB_BLOCK(mp
) != XFS_AGI_BLOCK(mp
) &&
3913 XFS_AGF_BLOCK(mp
) != XFS_AGI_BLOCK(mp
))
3914 set_dbmap(agno
, XFS_AGI_BLOCK(mp
), 1, DBM_AGI
, agno
,
3919 INT_GET(agf
->agf_roots
[XFS_BTNUM_BNO
], ARCH_CONVERT
),
3920 INT_GET(agf
->agf_levels
[XFS_BTNUM_BNO
], ARCH_CONVERT
),
3921 1, scanfunc_bno
, TYP_BNOBT
);
3924 INT_GET(agf
->agf_roots
[XFS_BTNUM_CNT
], ARCH_CONVERT
),
3925 INT_GET(agf
->agf_levels
[XFS_BTNUM_CNT
], ARCH_CONVERT
),
3926 1, scanfunc_cnt
, TYP_CNTBT
);
3928 INT_GET(agi
->agi_root
, ARCH_CONVERT
),
3929 INT_GET(agi
->agi_level
, ARCH_CONVERT
),
3930 1, scanfunc_ino
, TYP_INOBT
);
3931 if (INT_GET(agf
->agf_freeblks
, ARCH_CONVERT
) != agffreeblks
) {
3933 dbprintf("agf_freeblks %u, counted %u in ag %u\n",
3934 INT_GET(agf
->agf_freeblks
, ARCH_CONVERT
),
3938 if (INT_GET(agf
->agf_longest
, ARCH_CONVERT
) != agflongest
) {
3940 dbprintf("agf_longest %u, counted %u in ag %u\n",
3941 INT_GET(agf
->agf_longest
, ARCH_CONVERT
),
3945 if (INT_GET(agi
->agi_count
, ARCH_CONVERT
) != agicount
) {
3947 dbprintf("agi_count %u, counted %u in ag %u\n",
3948 INT_GET(agi
->agi_count
, ARCH_CONVERT
),
3952 if (INT_GET(agi
->agi_freecount
, ARCH_CONVERT
) != agifreecount
) {
3954 dbprintf("agi_freecount %u, counted %u in ag %u\n",
3955 INT_GET(agi
->agi_freecount
, ARCH_CONVERT
),
3956 agifreecount
, agno
);
3959 for (i
= 0; i
< XFS_AGI_UNLINKED_BUCKETS
; i
++) {
3960 if (INT_GET(agi
->agi_unlinked
[i
], ARCH_CONVERT
) != NULLAGINO
) {
3962 xfs_agino_t agino
=INT_GET(agi
->agi_unlinked
[i
], ARCH_CONVERT
);
3963 dbprintf("agi unlinked bucket %d is %u in ag "
3964 "%u (inode=%lld)\n", i
, agino
, agno
,
3965 XFS_AGINO_TO_INO(mp
, agno
, agino
));
3979 xfs_agnumber_t seqno
= INT_GET(agf
->agf_seqno
, ARCH_CONVERT
);
3985 if (XFS_SB_BLOCK(mp
) != XFS_AGFL_BLOCK(mp
) &&
3986 XFS_AGF_BLOCK(mp
) != XFS_AGFL_BLOCK(mp
) &&
3987 XFS_AGI_BLOCK(mp
) != XFS_AGFL_BLOCK(mp
))
3988 set_dbmap(seqno
, XFS_AGFL_BLOCK(mp
), 1, DBM_AGFL
, seqno
,
3990 if (INT_GET(agf
->agf_flcount
, ARCH_CONVERT
) == 0)
3993 set_cur(&typtab
[TYP_AGFL
],
3994 XFS_AG_DADDR(mp
, seqno
, XFS_AGFL_DADDR(mp
)),
3995 XFS_FSS_TO_BB(mp
, 1), DB_RING_IGN
, NULL
);
3996 if ((agfl
= iocur_top
->data
) == NULL
) {
3997 dbprintf("can't read agfl block for ag %u\n", seqno
);
4001 i
= INT_GET(agf
->agf_flfirst
, ARCH_CONVERT
);
4004 bno
= INT_GET(agfl
->agfl_bno
[i
], ARCH_CONVERT
);
4005 set_dbmap(seqno
, bno
, 1, DBM_FREELIST
, seqno
,
4006 XFS_AGFL_BLOCK(mp
));
4008 if (i
== INT_GET(agf
->agf_fllast
, ARCH_CONVERT
))
4010 if (++i
== XFS_AGFL_SIZE(mp
))
4013 if (count
!= INT_GET(agf
->agf_flcount
, ARCH_CONVERT
)) {
4015 dbprintf("freeblk count %u != flcount %u in ag %u\n",
4016 count
, INT_GET(agf
->agf_flcount
, ARCH_CONVERT
),
4028 scan_lbtree_f_t func
,
4031 xfs_drfsbno_t
*totd
,
4032 xfs_drfsbno_t
*toti
,
4039 set_cur(&typtab
[btype
], XFS_FSB_TO_DADDR(mp
, root
), blkbb
, DB_RING_IGN
,
4041 if (iocur_top
->data
== NULL
) {
4043 dbprintf("can't read btree block %u/%u\n",
4044 XFS_FSB_TO_AGNO(mp
, root
),
4045 XFS_FSB_TO_AGBNO(mp
, root
));
4049 (*func
)(iocur_top
->data
, nlevels
- 1, type
, root
, id
, totd
, toti
, nex
,
4050 blkmapp
, isroot
, btype
);
4060 scan_sbtree_f_t func
,
4063 xfs_agnumber_t seqno
= INT_GET(agf
->agf_seqno
, ARCH_CONVERT
);
4066 set_cur(&typtab
[btype
],
4067 XFS_AGB_TO_DADDR(mp
, seqno
, root
), blkbb
, DB_RING_IGN
, NULL
);
4068 if (iocur_top
->data
== NULL
) {
4070 dbprintf("can't read btree block %u/%u\n", seqno
, root
);
4074 (*func
)(iocur_top
->data
, nlevels
- 1, agf
, root
, isroot
);
4080 xfs_btree_lblock_t
*ablock
,
4085 xfs_drfsbno_t
*totd
,
4086 xfs_drfsbno_t
*toti
,
4092 xfs_agblock_t agbno
;
4093 xfs_agnumber_t agno
;
4094 xfs_bmbt_block_t
*block
= (xfs_bmbt_block_t
*)ablock
;
4097 xfs_bmbt_rec_32_t
*rp
;
4099 agno
= XFS_FSB_TO_AGNO(mp
, bno
);
4100 agbno
= XFS_FSB_TO_AGBNO(mp
, bno
);
4101 if (INT_GET(block
->bb_magic
, ARCH_CONVERT
) != XFS_BMAP_MAGIC
) {
4102 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
4103 dbprintf("bad magic # %#x in inode %lld bmbt block "
4105 INT_GET(block
->bb_magic
, ARCH_CONVERT
), id
->ino
, agno
, agbno
);
4108 if (INT_GET(block
->bb_level
, ARCH_CONVERT
) != level
) {
4109 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
4110 dbprintf("expected level %d got %d in inode %lld bmbt "
4112 level
, INT_GET(block
->bb_level
, ARCH_CONVERT
), id
->ino
, agno
, agbno
);
4115 set_dbmap(agno
, agbno
, 1, type
, agno
, agbno
);
4116 set_inomap(agno
, agbno
, 1, id
);
4119 if (INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) > mp
->m_bmap_dmxr
[0] ||
4120 (isroot
== 0 && INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) < mp
->m_bmap_dmnr
[0])) {
4121 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
4122 dbprintf("bad btree nrecs (%u, min=%u, max=%u) "
4123 "in inode %lld bmap block %lld\n",
4124 INT_GET(block
->bb_numrecs
, ARCH_CONVERT
), mp
->m_bmap_dmnr
[0],
4125 mp
->m_bmap_dmxr
[0], id
->ino
,
4130 rp
= (xfs_bmbt_rec_32_t
*)
4131 XFS_BTREE_REC_ADDR(mp
->m_sb
.sb_blocksize
, xfs_bmbt
,
4132 block
, 1, mp
->m_bmap_dmxr
[0]);
4133 *nex
+= INT_GET(block
->bb_numrecs
, ARCH_CONVERT
);
4134 process_bmbt_reclist(rp
, INT_GET(block
->bb_numrecs
, ARCH_CONVERT
), type
, id
, totd
,
4138 if (INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) > mp
->m_bmap_dmxr
[1] ||
4139 (isroot
== 0 && INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) < mp
->m_bmap_dmnr
[1])) {
4140 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
4141 dbprintf("bad btree nrecs (%u, min=%u, max=%u) in "
4142 "inode %lld bmap block %lld\n",
4143 INT_GET(block
->bb_numrecs
, ARCH_CONVERT
), mp
->m_bmap_dmnr
[1],
4144 mp
->m_bmap_dmxr
[1], id
->ino
, (xfs_dfsbno_t
)bno
);
4148 pp
= XFS_BTREE_PTR_ADDR(mp
->m_sb
.sb_blocksize
, xfs_bmbt
, block
, 1,
4149 mp
->m_bmap_dmxr
[0]);
4150 for (i
= 0; i
< INT_GET(block
->bb_numrecs
, ARCH_CONVERT
); i
++)
4151 scan_lbtree(INT_GET(pp
[i
], ARCH_CONVERT
), level
, scanfunc_bmap
, type
, id
, totd
, toti
,
4152 nex
, blkmapp
, 0, btype
);
4157 xfs_btree_sblock_t
*ablock
,
4163 xfs_alloc_block_t
*block
= (xfs_alloc_block_t
*)ablock
;
4165 xfs_alloc_ptr_t
*pp
;
4166 xfs_alloc_rec_t
*rp
;
4167 xfs_agnumber_t seqno
= INT_GET(agf
->agf_seqno
, ARCH_CONVERT
);
4169 if (INT_GET(block
->bb_magic
, ARCH_CONVERT
) != XFS_ABTB_MAGIC
) {
4170 dbprintf("bad magic # %#x in btbno block %u/%u\n",
4171 INT_GET(block
->bb_magic
, ARCH_CONVERT
), seqno
, bno
);
4176 if (INT_GET(block
->bb_level
, ARCH_CONVERT
) != level
) {
4178 dbprintf("expected level %d got %d in btbno block "
4180 level
, INT_GET(block
->bb_level
, ARCH_CONVERT
), seqno
, bno
);
4183 set_dbmap(seqno
, bno
, 1, DBM_BTBNO
, seqno
, bno
);
4185 if (INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) > mp
->m_alloc_mxr
[0] ||
4186 (isroot
== 0 && INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) < mp
->m_alloc_mnr
[0])) {
4187 dbprintf("bad btree nrecs (%u, min=%u, max=%u) in "
4188 "btbno block %u/%u\n",
4189 INT_GET(block
->bb_numrecs
, ARCH_CONVERT
), mp
->m_alloc_mnr
[0],
4190 mp
->m_alloc_mxr
[0], seqno
, bno
);
4194 rp
= XFS_BTREE_REC_ADDR(mp
->m_sb
.sb_blocksize
, xfs_alloc
, block
,
4195 1, mp
->m_alloc_mxr
[0]);
4196 for (i
= 0; i
< INT_GET(block
->bb_numrecs
, ARCH_CONVERT
); i
++) {
4197 set_dbmap(seqno
, INT_GET(rp
[i
].ar_startblock
, ARCH_CONVERT
),
4198 INT_GET(rp
[i
].ar_blockcount
, ARCH_CONVERT
), DBM_FREE1
,
4203 if (INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) > mp
->m_alloc_mxr
[1] ||
4204 (isroot
== 0 && INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) < mp
->m_alloc_mnr
[1])) {
4205 dbprintf("bad btree nrecs (%u, min=%u, max=%u) in btbno block "
4207 INT_GET(block
->bb_numrecs
, ARCH_CONVERT
), mp
->m_alloc_mnr
[1],
4208 mp
->m_alloc_mxr
[1], seqno
, bno
);
4212 pp
= XFS_BTREE_PTR_ADDR(mp
->m_sb
.sb_blocksize
, xfs_alloc
, block
, 1,
4213 mp
->m_alloc_mxr
[1]);
4214 for (i
= 0; i
< INT_GET(block
->bb_numrecs
, ARCH_CONVERT
); i
++)
4215 scan_sbtree(agf
, INT_GET(pp
[i
], ARCH_CONVERT
), level
, 0, scanfunc_bno
, TYP_BNOBT
);
4220 xfs_btree_sblock_t
*ablock
,
4226 xfs_alloc_block_t
*block
= (xfs_alloc_block_t
*)ablock
;
4227 xfs_agnumber_t seqno
= INT_GET(agf
->agf_seqno
, ARCH_CONVERT
);
4229 xfs_alloc_ptr_t
*pp
;
4230 xfs_alloc_rec_t
*rp
;
4232 if (INT_GET(block
->bb_magic
, ARCH_CONVERT
) != XFS_ABTC_MAGIC
) {
4233 dbprintf("bad magic # %#x in btcnt block %u/%u\n",
4234 INT_GET(block
->bb_magic
, ARCH_CONVERT
), seqno
, bno
);
4239 if (INT_GET(block
->bb_level
, ARCH_CONVERT
) != level
) {
4241 dbprintf("expected level %d got %d in btcnt block "
4243 level
, INT_GET(block
->bb_level
, ARCH_CONVERT
), seqno
, bno
);
4246 set_dbmap(seqno
, bno
, 1, DBM_BTCNT
, seqno
, bno
);
4248 if (INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) > mp
->m_alloc_mxr
[0] ||
4249 (isroot
== 0 && INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) < mp
->m_alloc_mnr
[0])) {
4250 dbprintf("bad btree nrecs (%u, min=%u, max=%u) in "
4251 "btbno block %u/%u\n",
4252 INT_GET(block
->bb_numrecs
, ARCH_CONVERT
), mp
->m_alloc_mnr
[0],
4253 mp
->m_alloc_mxr
[0], seqno
, bno
);
4257 rp
= XFS_BTREE_REC_ADDR(mp
->m_sb
.sb_blocksize
, xfs_alloc
, block
,
4258 1, mp
->m_alloc_mxr
[0]);
4259 for (i
= 0; i
< INT_GET(block
->bb_numrecs
, ARCH_CONVERT
); i
++) {
4260 check_set_dbmap(seqno
, INT_GET(rp
[i
].ar_startblock
, ARCH_CONVERT
),
4261 INT_GET(rp
[i
].ar_blockcount
, ARCH_CONVERT
), DBM_FREE1
, DBM_FREE2
,
4263 fdblocks
+= INT_GET(rp
[i
].ar_blockcount
, ARCH_CONVERT
);
4264 agffreeblks
+= INT_GET(rp
[i
].ar_blockcount
, ARCH_CONVERT
);
4265 if (INT_GET(rp
[i
].ar_blockcount
, ARCH_CONVERT
) > agflongest
)
4266 agflongest
= INT_GET(rp
[i
].ar_blockcount
, ARCH_CONVERT
);
4270 if (INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) > mp
->m_alloc_mxr
[1] ||
4271 (isroot
== 0 && INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) < mp
->m_alloc_mnr
[1])) {
4272 dbprintf("bad btree nrecs (%u, min=%u, max=%u) in btbno block "
4274 INT_GET(block
->bb_numrecs
, ARCH_CONVERT
), mp
->m_alloc_mnr
[1],
4275 mp
->m_alloc_mxr
[1], seqno
, bno
);
4279 pp
= XFS_BTREE_PTR_ADDR(mp
->m_sb
.sb_blocksize
, xfs_alloc
, block
, 1,
4280 mp
->m_alloc_mxr
[1]);
4281 for (i
= 0; i
< INT_GET(block
->bb_numrecs
, ARCH_CONVERT
); i
++)
4282 scan_sbtree(agf
, INT_GET(pp
[i
], ARCH_CONVERT
), level
, 0, scanfunc_cnt
, TYP_CNTBT
);
4287 xfs_btree_sblock_t
*ablock
,
4294 xfs_inobt_block_t
*block
= (xfs_inobt_block_t
*)ablock
;
4295 xfs_agnumber_t seqno
= INT_GET(agf
->agf_seqno
, ARCH_CONVERT
);
4301 xfs_inobt_ptr_t
*pp
;
4302 xfs_inobt_rec_t
*rp
;
4304 if (INT_GET(block
->bb_magic
, ARCH_CONVERT
) != XFS_IBT_MAGIC
) {
4305 dbprintf("bad magic # %#x in inobt block %u/%u\n",
4306 INT_GET(block
->bb_magic
, ARCH_CONVERT
), seqno
, bno
);
4310 if (INT_GET(block
->bb_level
, ARCH_CONVERT
) != level
) {
4312 dbprintf("expected level %d got %d in inobt block "
4314 level
, INT_GET(block
->bb_level
, ARCH_CONVERT
), seqno
, bno
);
4317 set_dbmap(seqno
, bno
, 1, DBM_BTINO
, seqno
, bno
);
4319 if (INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) > mp
->m_inobt_mxr
[0] ||
4320 (isroot
== 0 && INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) < mp
->m_inobt_mnr
[0])) {
4321 dbprintf("bad btree nrecs (%u, min=%u, max=%u) in "
4322 "inobt block %u/%u\n",
4323 INT_GET(block
->bb_numrecs
, ARCH_CONVERT
), mp
->m_inobt_mnr
[0],
4324 mp
->m_inobt_mxr
[0], seqno
, bno
);
4328 rp
= XFS_BTREE_REC_ADDR(mp
->m_sb
.sb_blocksize
, xfs_inobt
, block
,
4329 1, mp
->m_inobt_mxr
[0]);
4330 for (i
= 0; i
< INT_GET(block
->bb_numrecs
, ARCH_CONVERT
); i
++) {
4331 agino
= INT_GET(rp
[i
].ir_startino
, ARCH_CONVERT
);
4332 off
= XFS_INO_TO_OFFSET(mp
, agino
);
4334 if ((sbversion
& XFS_SB_VERSION_ALIGNBIT
) &&
4335 mp
->m_sb
.sb_inoalignmt
&&
4336 (XFS_INO_TO_AGBNO(mp
, agino
) %
4337 mp
->m_sb
.sb_inoalignmt
))
4338 sbversion
&= ~XFS_SB_VERSION_ALIGNBIT
;
4339 set_dbmap(seqno
, XFS_AGINO_TO_AGBNO(mp
, agino
),
4340 (xfs_extlen_t
)MAX(1,
4341 XFS_INODES_PER_CHUNK
>>
4342 mp
->m_sb
.sb_inopblog
),
4343 DBM_INODE
, seqno
, bno
);
4345 icount
+= XFS_INODES_PER_CHUNK
;
4346 agicount
+= XFS_INODES_PER_CHUNK
;
4347 ifree
+= INT_GET(rp
[i
].ir_freecount
, ARCH_CONVERT
);
4348 agifreecount
+= INT_GET(rp
[i
].ir_freecount
, ARCH_CONVERT
);
4350 set_cur(&typtab
[TYP_INODE
],
4351 XFS_AGB_TO_DADDR(mp
, seqno
,
4352 XFS_AGINO_TO_AGBNO(mp
, agino
)),
4353 (int)XFS_FSB_TO_BB(mp
, XFS_IALLOC_BLOCKS(mp
)),
4355 if (iocur_top
->data
== NULL
) {
4357 dbprintf("can't read inode block "
4360 XFS_AGINO_TO_AGBNO(mp
, agino
));
4364 for (j
= 0, nfree
= 0; j
< XFS_INODES_PER_CHUNK
; j
++) {
4365 if ((isfree
= XFS_INOBT_IS_FREE(&rp
[i
], j
, ARCH_CONVERT
)))
4367 process_inode(agf
, agino
+ j
,
4368 (xfs_dinode_t
*)((char *)iocur_top
->data
+ ((off
+ j
) << mp
->m_sb
.sb_inodelog
)),
4371 if (nfree
!= INT_GET(rp
[i
].ir_freecount
, ARCH_CONVERT
)) {
4373 dbprintf("ir_freecount/free mismatch, "
4374 "inode chunk %u/%u, freecount "
4377 INT_GET(rp
[i
].ir_freecount
, ARCH_CONVERT
), nfree
);
4384 if (INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) > mp
->m_inobt_mxr
[1] ||
4385 (isroot
== 0 && INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) < mp
->m_inobt_mnr
[1])) {
4386 dbprintf("bad btree nrecs (%u, min=%u, max=%u) in inobt block "
4388 INT_GET(block
->bb_numrecs
, ARCH_CONVERT
), mp
->m_inobt_mnr
[1],
4389 mp
->m_inobt_mxr
[1], seqno
, bno
);
4393 pp
= XFS_BTREE_PTR_ADDR(mp
->m_sb
.sb_blocksize
, xfs_inobt
, block
, 1,
4394 mp
->m_inobt_mxr
[1]);
4395 for (i
= 0; i
< INT_GET(block
->bb_numrecs
, ARCH_CONVERT
); i
++)
4396 scan_sbtree(agf
, INT_GET(pp
[i
], ARCH_CONVERT
), level
, 0, scanfunc_ino
, TYP_INOBT
);
4401 xfs_agnumber_t agno
,
4402 xfs_agblock_t agbno
,
4405 xfs_agnumber_t c_agno
,
4406 xfs_agblock_t c_agbno
)
4408 check_set_dbmap(agno
, agbno
, len
, DBM_UNKNOWN
, type
, c_agno
, c_agbno
);
4413 xfs_agnumber_t agno
,
4414 xfs_agblock_t agbno
,
4422 if (!check_inomap(agno
, agbno
, len
, id
->ino
))
4424 mayprint
= verbose
| id
->ilist
| blist_size
;
4425 for (i
= 0, idp
= &inomap
[agno
][agbno
]; i
< len
; i
++, idp
++) {
4428 (verbose
|| id
->ilist
|| CHECK_BLISTA(agno
, agbno
+ i
)))
4429 dbprintf("setting inode to %lld for block %u/%u\n",
4430 id
->ino
, agno
, agbno
+ i
);
4440 check_set_rdbmap(bno
, len
, DBM_UNKNOWN
, type
);
4453 if (!check_rinomap(bno
, len
, id
->ino
))
4455 mayprint
= verbose
| id
->ilist
| blist_size
;
4456 for (i
= 0, idp
= &inomap
[mp
->m_sb
.sb_agcount
][bno
];
4460 if (mayprint
&& (verbose
|| id
->ilist
|| CHECK_BLIST(bno
+ i
)))
4461 dbprintf("setting inode to %lld for rtblock %llu\n",
4473 id
->link_set
= nlink
;
4475 id
->security
= security
;
4476 if (verbose
|| id
->ilist
)
4477 dbprintf("inode %lld nlink %u %s dir\n", id
->ino
, nlink
,
4478 isdir
? "is" : "not");