2 * Copyright (c) 2000 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/
48 DBM_UNKNOWN
, DBM_AGF
, DBM_AGFL
, DBM_AGI
,
49 DBM_ATTR
, DBM_BTBMAPA
, DBM_BTBMAPD
, DBM_BTBNO
,
50 DBM_BTCNT
, DBM_BTINO
, DBM_DATA
, DBM_DIR
,
51 DBM_FREE1
, DBM_FREE2
, DBM_FREELIST
, DBM_INODE
,
52 DBM_LOG
, DBM_MISSING
, DBM_QUOTA
, DBM_RTBITMAP
,
53 DBM_RTDATA
, DBM_RTFREE
, DBM_RTSUM
, DBM_SB
,
58 typedef struct inodata
{
66 struct inodata
*parent
;
69 #define MIN_INODATA_HASH_SIZE 256
70 #define MAX_INODATA_HASH_SIZE 65536
71 #define INODATA_AVG_HASH_LENGTH 8
73 typedef struct qinfo
{
79 #define QDATA_HASH_SIZE 256
80 typedef struct qdata
{
87 typedef struct blkent
{
88 xfs_fileoff_t startoff
;
90 xfs_fsblock_t blks
[1];
92 #define BLKENT_SIZE(n) \
93 (offsetof(blkent_t, blks) + (sizeof(xfs_fsblock_t) * (n)))
95 typedef struct blkmap
{
100 #define BLKMAP_SIZE(n) \
101 (offsetof(blkmap_t, ents) + (sizeof(blkent_t *) * (n)))
103 typedef struct freetab
{
106 xfs_dir2_data_off_t ents
[1];
108 #define FREETAB_SIZE(n) \
109 (offsetof(freetab_t, ents) + (sizeof(xfs_dir2_data_off_t) * (n)))
111 typedef struct dirhash
{
112 struct dirhash
*next
;
113 xfs_dir2_leaf_entry_t entry
;
116 #define DIR_HASH_SIZE 1024
117 #define DIR_HASH_FUNC(h,a) (((h) ^ (a)) % DIR_HASH_SIZE)
119 static xfs_extlen_t agffreeblks
;
120 static xfs_extlen_t agflongest
;
121 static xfs_agino_t agicount
;
122 static xfs_agino_t agifreecount
;
123 static xfs_fsblock_t
*blist
;
124 static int blist_size
;
125 static char **dbmap
; /* really dbm_t:8 */
126 static dirhash_t
**dirhash
;
128 static __uint64_t fdblocks
;
129 static __uint64_t frextents
;
130 static __uint64_t icount
;
131 static __uint64_t ifree
;
132 static inodata_t
***inodata
;
133 static int inodata_hash_size
;
134 static inodata_t
***inomap
;
137 static qdata_t
**qpdata
;
139 static qdata_t
**qudata
;
141 static unsigned sbversion
;
142 static int sbver_err
;
143 static int serious_error
;
145 static xfs_suminfo_t
*sumcompute
;
146 static xfs_suminfo_t
*sumfile
;
147 static const char *typename
[] = {
177 #define CHECK_BLIST(b) (blist_size && check_blist(b))
178 #define CHECK_BLISTA(a,b) \
179 (blist_size && check_blist(XFS_AGB_TO_FSB(mp, a, b)))
181 typedef void (*scan_lbtree_f_t
)(xfs_btree_lblock_t
*block
,
193 typedef void (*scan_sbtree_f_t
)(xfs_btree_sblock_t
*block
,
199 static void add_blist(xfs_fsblock_t bno
);
200 static void add_ilist(xfs_ino_t ino
);
201 static void addlink_inode(inodata_t
*id
);
202 static void addname_inode(inodata_t
*id
, char *name
, int namelen
);
203 static void addparent_inode(inodata_t
*id
, xfs_ino_t parent
);
204 static void blkent_append(blkent_t
**entp
, xfs_fsblock_t b
,
206 static blkent_t
*blkent_new(xfs_fileoff_t o
, xfs_fsblock_t b
,
208 static void blkent_prepend(blkent_t
**entp
, xfs_fsblock_t b
,
210 static blkmap_t
*blkmap_alloc(xfs_extnum_t
);
211 static void blkmap_free(blkmap_t
*blkmap
);
212 static xfs_fsblock_t
blkmap_get(blkmap_t
*blkmap
, xfs_fileoff_t o
);
213 static int blkmap_getn(blkmap_t
*blkmap
, xfs_fileoff_t o
, int nb
,
215 static void blkmap_grow(blkmap_t
**blkmapp
, blkent_t
**entp
,
217 static xfs_fileoff_t
blkmap_next_off(blkmap_t
*blkmap
, xfs_fileoff_t o
,
219 static void blkmap_set_blk(blkmap_t
**blkmapp
, xfs_fileoff_t o
,
221 static void blkmap_set_ext(blkmap_t
**blkmapp
, xfs_fileoff_t o
,
222 xfs_fsblock_t b
, xfs_extlen_t c
);
223 static void blkmap_shrink(blkmap_t
*blkmap
, blkent_t
**entp
);
224 static int blockfree_f(int argc
, char **argv
);
225 static int blockget_f(int argc
, char **argv
);
227 static int blocktrash_f(int argc
, char **argv
);
229 static int blockuse_f(int argc
, char **argv
);
230 static int check_blist(xfs_fsblock_t bno
);
231 static void check_dbmap(xfs_agnumber_t agno
, xfs_agblock_t agbno
,
232 xfs_extlen_t len
, dbm_t type
);
233 static int check_inomap(xfs_agnumber_t agno
, xfs_agblock_t agbno
,
234 xfs_extlen_t len
, xfs_ino_t c_ino
);
235 static void check_linkcounts(xfs_agnumber_t agno
);
236 static int check_range(xfs_agnumber_t agno
, xfs_agblock_t agbno
,
238 static void check_rdbmap(xfs_drfsbno_t bno
, xfs_extlen_t len
,
240 static int check_rinomap(xfs_drfsbno_t bno
, xfs_extlen_t len
,
242 static void check_rootdir(void);
243 static int check_rrange(xfs_drfsbno_t bno
, xfs_extlen_t len
);
244 static void check_set_dbmap(xfs_agnumber_t agno
,
245 xfs_agblock_t agbno
, xfs_extlen_t len
,
246 dbm_t type1
, dbm_t type2
,
247 xfs_agnumber_t c_agno
,
248 xfs_agblock_t c_agbno
);
249 static void check_set_rdbmap(xfs_drfsbno_t bno
, xfs_extlen_t len
,
250 dbm_t type1
, dbm_t type2
);
251 static void check_summary(void);
252 static void checknot_dbmap(xfs_agnumber_t agno
, xfs_agblock_t agbno
,
253 xfs_extlen_t len
, int typemask
);
254 static void checknot_rdbmap(xfs_drfsbno_t bno
, xfs_extlen_t len
,
256 static void dir_hash_add(xfs_dahash_t hash
,
257 xfs_dir2_dataptr_t addr
);
258 static void dir_hash_check(inodata_t
*id
, int v
);
259 static void dir_hash_done(void);
260 static void dir_hash_init(void);
261 static int dir_hash_see(xfs_dahash_t hash
,
262 xfs_dir2_dataptr_t addr
);
263 static inodata_t
*find_inode(xfs_ino_t ino
, int add
);
264 static void free_inodata(xfs_agnumber_t agno
);
265 static int init(int argc
, char **argv
);
266 static char *inode_name(xfs_ino_t ino
, inodata_t
**ipp
);
267 static int ncheck_f(int argc
, char **argv
);
268 static char *prepend_path(char *oldpath
, char *parent
);
269 static xfs_ino_t
process_block_dir_v2(blkmap_t
*blkmap
, int *dot
,
270 int *dotdot
, inodata_t
*id
);
271 static void process_bmbt_reclist(xfs_bmbt_rec_32_t
*rp
, int numrecs
,
272 dbm_t type
, inodata_t
*id
,
275 static void process_btinode(inodata_t
*id
, xfs_dinode_t
*dip
,
276 dbm_t type
, xfs_drfsbno_t
*totd
,
277 xfs_drfsbno_t
*toti
, xfs_extnum_t
*nex
,
278 blkmap_t
**blkmapp
, int whichfork
);
279 static xfs_ino_t
process_data_dir_v2(int *dot
, int *dotdot
,
280 inodata_t
*id
, int v
,
282 freetab_t
**freetabp
);
283 static xfs_dir2_data_free_t
284 *process_data_dir_v2_freefind(xfs_dir2_data_t
*data
,
285 xfs_dir2_data_unused_t
*dup
);
286 static void process_dir(xfs_dinode_t
*dip
, blkmap_t
*blkmap
,
288 static int process_dir_v1(xfs_dinode_t
*dip
, blkmap_t
*blkmap
,
289 int *dot
, int *dotdot
, inodata_t
*id
,
291 static int process_dir_v2(xfs_dinode_t
*dip
, blkmap_t
*blkmap
,
292 int *dot
, int *dotdot
, inodata_t
*id
,
294 static void process_exinode(inodata_t
*id
, xfs_dinode_t
*dip
,
295 dbm_t type
, xfs_drfsbno_t
*totd
,
296 xfs_drfsbno_t
*toti
, xfs_extnum_t
*nex
,
297 blkmap_t
**blkmapp
, int whichfork
);
298 static void process_inode(xfs_agf_t
*agf
, xfs_agino_t agino
,
299 xfs_dinode_t
*dip
, int isfree
);
300 static void process_lclinode(inodata_t
*id
, xfs_dinode_t
*dip
,
301 dbm_t type
, xfs_drfsbno_t
*totd
,
302 xfs_drfsbno_t
*toti
, xfs_extnum_t
*nex
,
303 blkmap_t
**blkmapp
, int whichfork
);
304 static xfs_ino_t
process_leaf_dir_v1(blkmap_t
*blkmap
, int *dot
,
305 int *dotdot
, inodata_t
*id
);
306 static xfs_ino_t
process_leaf_dir_v1_int(int *dot
, int *dotdot
,
308 static xfs_ino_t
process_leaf_node_dir_v2(blkmap_t
*blkmap
, int *dot
,
309 int *dotdot
, inodata_t
*id
,
310 xfs_fsize_t dirsize
);
311 static void process_leaf_node_dir_v2_free(inodata_t
*id
, int v
,
314 static void process_leaf_node_dir_v2_int(inodata_t
*id
, int v
,
317 static xfs_ino_t
process_node_dir_v1(blkmap_t
*blkmap
, int *dot
,
318 int *dotdot
, inodata_t
*id
);
319 static void process_quota(int isproj
, inodata_t
*id
,
321 static void process_rtbitmap(blkmap_t
*blkmap
);
322 static void process_rtsummary(blkmap_t
*blkmap
);
323 static xfs_ino_t
process_sf_dir_v2(xfs_dinode_t
*dip
, int *dot
,
324 int *dotdot
, inodata_t
*id
);
325 static xfs_ino_t
process_shortform_dir_v1(xfs_dinode_t
*dip
, int *dot
,
326 int *dotdot
, inodata_t
*id
);
327 static void quota_add(xfs_dqid_t projid
, xfs_dqid_t userid
,
328 int dq
, xfs_qcnt_t bc
, xfs_qcnt_t ic
,
330 static void quota_add1(qdata_t
**qt
, xfs_dqid_t id
, int dq
,
331 xfs_qcnt_t bc
, xfs_qcnt_t ic
,
333 static void quota_check(char *s
, qdata_t
**qt
);
334 static void quota_init(void);
335 static void scan_ag(xfs_agnumber_t agno
);
336 static void scan_freelist(xfs_agf_t
*agf
);
337 static void scan_lbtree(xfs_fsblock_t root
, int nlevels
,
338 scan_lbtree_f_t func
, dbm_t type
,
339 inodata_t
*id
, xfs_drfsbno_t
*totd
,
340 xfs_drfsbno_t
*toti
, xfs_extnum_t
*nex
,
341 blkmap_t
**blkmapp
, int isroot
,
343 static void scan_sbtree(xfs_agf_t
*agf
, xfs_agblock_t root
,
344 int nlevels
, int isroot
,
345 scan_sbtree_f_t func
, typnm_t btype
);
346 static void scanfunc_bmap(xfs_btree_lblock_t
*ablock
, int level
,
347 dbm_t type
, xfs_fsblock_t bno
,
348 inodata_t
*id
, xfs_drfsbno_t
*totd
,
349 xfs_drfsbno_t
*toti
, xfs_extnum_t
*nex
,
350 blkmap_t
**blkmapp
, int isroot
,
352 static void scanfunc_bno(xfs_btree_sblock_t
*ablock
, int level
,
353 xfs_agf_t
*agf
, xfs_agblock_t bno
,
355 static void scanfunc_cnt(xfs_btree_sblock_t
*ablock
, int level
,
356 xfs_agf_t
*agf
, xfs_agblock_t bno
,
358 static void scanfunc_ino(xfs_btree_sblock_t
*ablock
, int level
,
359 xfs_agf_t
*agf
, xfs_agblock_t bno
,
361 static void set_dbmap(xfs_agnumber_t agno
, xfs_agblock_t agbno
,
362 xfs_extlen_t len
, dbm_t type
,
363 xfs_agnumber_t c_agno
, xfs_agblock_t c_agbno
);
364 static void set_inomap(xfs_agnumber_t agno
, xfs_agblock_t agbno
,
365 xfs_extlen_t len
, inodata_t
*id
);
366 static void set_rdbmap(xfs_drfsbno_t bno
, xfs_extlen_t len
,
368 static void set_rinomap(xfs_drfsbno_t bno
, xfs_extlen_t len
,
370 static void setlink_inode(inodata_t
*id
, nlink_t nlink
, int isdir
,
373 static const cmdinfo_t blockfree_cmd
=
374 { "blockfree", NULL
, blockfree_f
, 0, 0, 0,
375 NULL
, "free block usage information", NULL
};
376 static const cmdinfo_t blockget_cmd
=
377 { "blockget", "check", blockget_f
, 0, -1, 0,
378 "[-s|-v] [-n] [-b bno]... [-i ino] ...",
379 "get block usage and check consistency", NULL
};
381 static const cmdinfo_t blocktrash_cmd
=
382 { "blocktrash", NULL
, blocktrash_f
, 0, -1, 0,
383 "[-n count] [-x minlen] [-y maxlen] [-s seed] [-0123] [-t type] ...",
384 "trash randomly selected block(s)", NULL
};
386 static const cmdinfo_t blockuse_cmd
=
387 { "blockuse", NULL
, blockuse_f
, 0, 3, 0,
388 "[-n] [-c blockcount]",
389 "print usage for current block(s)", NULL
};
390 static const cmdinfo_t ncheck_cmd
=
391 { "ncheck", NULL
, ncheck_f
, 0, -1, 0,
393 "print inode-name pairs", NULL
};
401 blist
= xrealloc(blist
, blist_size
* sizeof(bno
));
402 blist
[blist_size
- 1] = bno
;
411 id
= find_inode(ino
, 1);
413 dbprintf("-i %lld bad inode number\n", ino
);
424 if (verbose
|| id
->ilist
)
425 dbprintf("inode %lld add link, now %u\n", id
->ino
,
435 if (!nflag
|| id
->name
)
437 id
->name
= xmalloc(namelen
+ 1);
438 memcpy(id
->name
, name
, namelen
);
439 id
->name
[namelen
] = '\0';
449 pid
= find_inode(parent
, 1);
451 if (verbose
|| id
->ilist
|| (pid
&& pid
->ilist
))
452 dbprintf("inode %lld parent %lld\n", id
->ino
, parent
);
465 *entp
= ent
= xrealloc(ent
, BLKENT_SIZE(c
+ ent
->nblks
));
466 for (i
= 0; i
< c
; i
++)
467 ent
->blks
[ent
->nblks
+ i
] = b
+ i
;
480 ent
= xmalloc(BLKENT_SIZE(c
));
483 for (i
= 0; i
< c
; i
++)
484 ent
->blks
[i
] = b
+ i
;
499 newent
= xmalloc(BLKENT_SIZE(oldent
->nblks
+ c
));
500 newent
->nblks
= oldent
->nblks
+ c
;
501 newent
->startoff
= oldent
->startoff
- c
;
502 for (i
= 0; i
< c
; i
++)
503 newent
->blks
[i
] = b
+ c
;
504 for (; i
< oldent
->nblks
+ c
; i
++)
505 newent
->blks
[i
] = oldent
->blks
[i
- c
];
518 blkmap
= xmalloc(BLKMAP_SIZE(nex
));
519 blkmap
->naents
= nex
;
531 for (i
= 0, entp
= blkmap
->ents
; i
< blkmap
->nents
; i
++, entp
++)
545 for (i
= 0, entp
= blkmap
->ents
; i
< blkmap
->nents
; i
++, entp
++) {
547 if (o
>= ent
->startoff
&& o
< ent
->startoff
+ ent
->nblks
)
548 return ent
->blks
[o
- ent
->startoff
];
567 for (i
= nex
= 0, bmp
= NULL
, entp
= blkmap
->ents
;
571 if (ent
->startoff
>= o
+ nb
)
573 if (ent
->startoff
+ ent
->nblks
<= o
)
575 for (ento
= ent
->startoff
;
576 ento
< ent
->startoff
+ ent
->nblks
&& ento
< o
+ nb
;
581 bmp
[nex
- 1].startoff
+ bmp
[nex
- 1].blockcount
==
583 bmp
[nex
- 1].startblock
+ bmp
[nex
- 1].blockcount
==
584 ent
->blks
[ento
- ent
->startoff
])
585 bmp
[nex
- 1].blockcount
++;
587 bmp
= realloc(bmp
, ++nex
* sizeof(*bmp
));
588 bmp
[nex
- 1].startoff
= ento
;
589 bmp
[nex
- 1].startblock
=
590 ent
->blks
[ento
- ent
->startoff
];
591 bmp
[nex
- 1].blockcount
= 1;
592 bmp
[nex
- 1].flag
= 0;
611 idx
= (int)(entp
- blkmap
->ents
);
612 if (blkmap
->naents
== blkmap
->nents
) {
613 blkmap
= xrealloc(blkmap
, BLKMAP_SIZE(blkmap
->nents
+ 1));
617 for (i
= blkmap
->nents
; i
> idx
; i
--)
618 blkmap
->ents
[i
] = blkmap
->ents
[i
- 1];
619 blkmap
->ents
[idx
] = newent
;
631 ent
= blkmap
->ents
[blkmap
->nents
- 1];
632 return ent
->startoff
+ ent
->nblks
;
646 if (o
== NULLFILEOFF
) {
648 ent
= blkmap
->ents
[0];
649 return ent
->startoff
;
651 entp
= &blkmap
->ents
[*t
];
653 if (o
< ent
->startoff
+ ent
->nblks
- 1)
656 if (entp
>= &blkmap
->ents
[blkmap
->nents
])
660 return ent
->startoff
;
675 for (entp
= blkmap
->ents
; entp
< &blkmap
->ents
[blkmap
->nents
]; entp
++) {
677 if (o
< ent
->startoff
- 1) {
678 ent
= blkent_new(o
, b
, 1);
679 blkmap_grow(blkmapp
, entp
, ent
);
682 if (o
== ent
->startoff
- 1) {
683 blkent_prepend(entp
, b
, 1);
686 if (o
>= ent
->startoff
&& o
< ent
->startoff
+ ent
->nblks
) {
687 ent
->blks
[o
- ent
->startoff
] = b
;
690 if (o
> ent
->startoff
+ ent
->nblks
)
692 blkent_append(entp
, b
, 1);
693 if (entp
== &blkmap
->ents
[blkmap
->nents
- 1])
697 if (ent
->startoff
+ ent
->nblks
< nextent
->startoff
)
699 blkent_append(entp
, nextent
->blks
[0], nextent
->nblks
);
700 blkmap_shrink(blkmap
, &entp
[1]);
703 ent
= blkent_new(o
, b
, 1);
704 blkmap_grow(blkmapp
, entp
, ent
);
720 if (!blkmap
->nents
) {
721 blkmap
->ents
[0] = blkent_new(o
, b
, c
);
725 entp
= &blkmap
->ents
[blkmap
->nents
- 1];
727 if (ent
->startoff
+ ent
->nblks
== o
) {
728 blkent_append(entp
, b
, c
);
731 if (ent
->startoff
+ ent
->nblks
< o
) {
732 ent
= blkent_new(o
, b
, c
);
733 blkmap_grow(blkmapp
, &blkmap
->ents
[blkmap
->nents
], ent
);
736 for (i
= 0; i
< c
; i
++)
737 blkmap_set_blk(blkmapp
, o
+ i
, b
+ i
);
749 idx
= (int)(entp
- blkmap
->ents
);
750 for (i
= idx
+ 1; i
< blkmap
->nents
; i
++)
751 blkmap
->ents
[i
] = blkmap
->ents
[i
- 1];
765 dbprintf("block usage information not allocated\n");
768 rt
= mp
->m_sb
.sb_rextents
!= 0;
769 for (c
= 0; c
< mp
->m_sb
.sb_agcount
; c
++) {
779 sumcompute
= sumfile
= NULL
;
791 * Check consistency of xfs filesystem contents.
803 dbprintf("already have block usage information\n");
806 if (!init(argc
, argv
))
808 oldprefix
= dbprefix
;
810 for (agno
= 0, sbyell
= 0; agno
< mp
->m_sb
.sb_agcount
; agno
++) {
812 if (sbver_err
> 4 && !sbyell
&& sbver_err
>= agno
) {
814 dbprintf("WARNING: this may be a newer XFS "
825 dbprefix
= oldprefix
;
829 for (agno
= 0; agno
< mp
->m_sb
.sb_agcount
; agno
++) {
831 * Check that there are no blocks either
832 * a) unaccounted for or
833 * b) bno-free but not cnt-free
835 checknot_dbmap(agno
, 0, mp
->m_sb
.sb_agblocks
,
836 (1 << DBM_UNKNOWN
) | (1 << DBM_FREE1
));
837 check_linkcounts(agno
);
839 if (mp
->m_sb
.sb_rblocks
) {
841 (xfs_extlen_t
)(mp
->m_sb
.sb_rextents
*
842 mp
->m_sb
.sb_rextsize
),
846 if (mp
->m_sb
.sb_icount
!= icount
) {
848 dbprintf("sb_icount %lld, counted %lld\n",
849 mp
->m_sb
.sb_icount
, icount
);
852 if (mp
->m_sb
.sb_ifree
!= ifree
) {
854 dbprintf("sb_ifree %lld, counted %lld\n",
855 mp
->m_sb
.sb_ifree
, ifree
);
858 if (mp
->m_sb
.sb_fdblocks
!= fdblocks
) {
860 dbprintf("sb_fdblocks %lld, counted %lld\n",
861 mp
->m_sb
.sb_fdblocks
, fdblocks
);
864 if (mp
->m_sb
.sb_frextents
!= frextents
) {
866 dbprintf("sb_frextents %lld, counted %lld\n",
867 mp
->m_sb
.sb_frextents
, frextents
);
870 if ((sbversion
& XFS_SB_VERSION_ATTRBIT
) &&
871 !XFS_SB_VERSION_HASATTR(&mp
->m_sb
)) {
873 dbprintf("sb versionnum missing attr bit %x\n",
874 XFS_SB_VERSION_ATTRBIT
);
877 if ((sbversion
& XFS_SB_VERSION_NLINKBIT
) &&
878 !XFS_SB_VERSION_HASNLINK(&mp
->m_sb
)) {
880 dbprintf("sb versionnum missing nlink bit %x\n",
881 XFS_SB_VERSION_NLINKBIT
);
884 if ((sbversion
& XFS_SB_VERSION_QUOTABIT
) &&
885 !XFS_SB_VERSION_HASQUOTA(&mp
->m_sb
)) {
887 dbprintf("sb versionnum missing quota bit %x\n",
888 XFS_SB_VERSION_QUOTABIT
);
891 if (!(sbversion
& XFS_SB_VERSION_ALIGNBIT
) &&
892 XFS_SB_VERSION_HASALIGN(&mp
->m_sb
)) {
894 dbprintf("sb versionnum extra align bit %x\n",
895 XFS_SB_VERSION_ALIGNBIT
);
899 quota_check("user", qudata
);
901 quota_check("project", qpdata
);
902 if (sbver_err
> mp
->m_sb
.sb_agcount
/ 2)
903 dbprintf("WARNING: this may be a newer XFS filesystem.\n");
906 dbprefix
= oldprefix
;
911 typedef struct ltab
{
932 static char *modestr
[] = {
933 "zeroed", "set", "flipped", "randomized"
936 len
= (int)((random() % (ltabp
->max
- ltabp
->min
+ 1)) + ltabp
->min
);
937 offset
= (int)(random() % (int)(mp
->m_sb
.sb_blocksize
* NBBY
));
940 set_cur(&typtab
[DBM_UNKNOWN
],
941 XFS_AGB_TO_DADDR(mp
, agno
, agbno
), blkbb
, DB_RING_IGN
, NULL
);
942 if ((buf
= iocur_top
->data
) == NULL
) {
943 dbprintf("can't read block %u/%u for trashing\n", agno
, agbno
);
947 for (bitno
= 0; bitno
< len
; bitno
++) {
948 bit
= (offset
+ bitno
) % (mp
->m_sb
.sb_blocksize
* NBBY
);
960 newbit
= (buf
[byte
] & mask
) == 0;
963 newbit
= (int)random() & 1;
973 printf("blocktrash: %u/%u %s block %d bit%s starting %d:%d %s\n",
974 agno
, agbno
, typename
[type
], len
, len
== 1 ? "" : "s",
975 offset
/ NBBY
, offset
% NBBY
, modestr
[mode
]);
986 xfs_drfsbno_t blocks
;
1005 dbprintf("must run blockget first\n");
1013 gettimeofday(&now
, NULL
);
1014 seed
= (unsigned int)(now
.tv_sec
^ now
.tv_usec
);
1017 goodmask
= (1 << DBM_AGF
) |
1021 (1 << DBM_BTBMAPA
) |
1022 (1 << DBM_BTBMAPD
) |
1029 (1 << DBM_RTBITMAP
) |
1032 while ((c
= getopt(argc
, argv
, "0123n:s:t:x:y:")) != EOF
) {
1047 count
= (int)strtol(optarg
, &p
, 0);
1048 if (*p
!= '\0' || count
<= 0) {
1049 dbprintf("bad blocktrash count %s\n", optarg
);
1054 seed
= (uint
)strtoul(optarg
, &p
, 0);
1058 for (i
= 0; typename
[i
]; i
++) {
1059 if (strcmp(typename
[i
], optarg
) == 0)
1062 if (!typename
[i
] || (((1 << i
) & goodmask
) == 0)) {
1063 dbprintf("bad blocktrash type %s\n", optarg
);
1069 min
= (int)strtol(optarg
, &p
, 0);
1070 if (*p
!= '\0' || min
<= 0 ||
1071 min
> mp
->m_sb
.sb_blocksize
* NBBY
) {
1072 dbprintf("bad blocktrash min %s\n", optarg
);
1077 max
= (int)strtol(optarg
, &p
, 0);
1078 if (*p
!= '\0' || max
<= 0 ||
1079 max
> mp
->m_sb
.sb_blocksize
* NBBY
) {
1080 dbprintf("bad blocktrash max %s\n", optarg
);
1085 dbprintf("bad option for blocktrash command\n");
1090 dbprintf("bad min/max for blocktrash command\n");
1095 lentab
= xmalloc(sizeof(ltab_t
));
1096 lentab
->min
= lentab
->max
= min
;
1098 for (i
= min
+ 1; i
<= max
; i
++) {
1099 if ((i
& (i
- 1)) == 0) {
1100 lentab
= xrealloc(lentab
,
1101 sizeof(ltab_t
) * (lentablen
+ 1));
1102 lentab
[lentablen
].min
= lentab
[lentablen
].max
= i
;
1105 lentab
[lentablen
- 1].max
= i
;
1107 for (blocks
= 0, agno
= 0; agno
< mp
->m_sb
.sb_agcount
; agno
++) {
1108 for (agbno
= 0, p
= dbmap
[agno
];
1109 agbno
< mp
->m_sb
.sb_agblocks
;
1111 if ((1 << *p
) & tmask
)
1116 dbprintf("blocktrash: no matching blocks\n");
1120 dbprintf("blocktrash: seed %u\n", seed
);
1122 for (i
= 0; i
< count
; i
++) {
1123 randb
= (xfs_drfsbno_t
)((((__int64_t
)random() << 32) |
1124 random()) % blocks
);
1125 for (bi
= 0, agno
= 0, done
= 0;
1126 !done
&& agno
< mp
->m_sb
.sb_agcount
;
1128 for (agbno
= 0, p
= dbmap
[agno
];
1129 agbno
< mp
->m_sb
.sb_agblocks
;
1131 if (!((1 << *p
) & tmask
))
1135 blocktrash_b(agno
, agbno
, (dbm_t
)*p
,
1136 &lentab
[random() % lentablen
], mode
);
1152 xfs_agblock_t agbno
;
1153 xfs_agnumber_t agno
;
1163 dbprintf("must run blockget first\n");
1169 fsb
= XFS_DADDR_TO_FSB(mp
, iocur_top
->off
>> BBSHIFT
);
1170 agno
= XFS_FSB_TO_AGNO(mp
, fsb
);
1171 end
= agbno
= XFS_FSB_TO_AGBNO(mp
, fsb
);
1172 while ((c
= getopt(argc
, argv
, "c:n")) != EOF
) {
1175 count
= (int)strtol(optarg
, &p
, 0);
1176 end
= agbno
+ count
- 1;
1177 if (*p
!= '\0' || count
<= 0 ||
1178 end
>= mp
->m_sb
.sb_agblocks
) {
1179 dbprintf("bad blockuse count %s\n", optarg
);
1185 dbprintf("must run blockget -n first\n");
1191 dbprintf("bad option for blockuse command\n");
1195 while (agbno
<= end
) {
1196 p
= &dbmap
[agno
][agbno
];
1197 i
= inomap
[agno
][agbno
];
1198 dbprintf("block %llu (%u/%u) type %s",
1199 (xfs_dfsbno_t
)XFS_AGB_TO_FSB(mp
, agno
, agbno
),
1200 agno
, agbno
, typename
[(dbm_t
)*p
]);
1202 dbprintf(" inode %lld", i
->ino
);
1203 if (shownames
&& (p
= inode_name(i
->ino
, NULL
))) {
1220 for (i
= 0; i
< blist_size
; i
++) {
1221 if (blist
[i
] == bno
)
1229 xfs_agnumber_t agno
,
1230 xfs_agblock_t agbno
,
1237 for (i
= 0, p
= &dbmap
[agno
][agbno
]; i
< len
; i
++, p
++) {
1238 if ((dbm_t
)*p
!= type
) {
1239 if (!sflag
|| CHECK_BLISTA(agno
, agbno
+ i
))
1240 dbprintf("block %u/%u expected type %s got "
1242 agno
, agbno
+ i
, typename
[type
],
1243 typename
[(dbm_t
)*p
]);
1252 add_command(&blockfree_cmd
);
1253 add_command(&blockget_cmd
);
1255 add_command(&blocktrash_cmd
);
1257 add_command(&blockuse_cmd
);
1258 add_command(&ncheck_cmd
);
1263 xfs_agnumber_t agno
,
1264 xfs_agblock_t agbno
,
1272 if (!check_range(agno
, agbno
, len
)) {
1273 dbprintf("blocks %u/%u..%u claimed by inode %lld\n",
1274 agno
, agbno
, agbno
+ len
- 1, c_ino
);
1277 for (i
= 0, rval
= 1, idp
= &inomap
[agno
][agbno
]; i
< len
; i
++, idp
++) {
1279 if (!sflag
|| (*idp
)->ilist
||
1280 CHECK_BLISTA(agno
, agbno
+ i
))
1281 dbprintf("block %u/%u claimed by inode %lld, "
1282 "previous inum %lld\n",
1283 agno
, agbno
+ i
, c_ino
, (*idp
)->ino
);
1293 xfs_agnumber_t agno
)
1301 for (idx
= 0; idx
< inodata_hash_size
; ht
++, idx
++) {
1304 if (ep
->link_set
!= ep
->link_add
|| ep
->link_set
== 0) {
1305 path
= inode_name(ep
->ino
, NULL
);
1306 if (!path
&& ep
->link_add
)
1307 path
= xstrdup("?");
1308 if (!sflag
|| ep
->ilist
) {
1310 dbprintf("link count mismatch "
1311 "for inode %lld (name "
1317 else if (ep
->link_set
)
1318 dbprintf("disconnected inode "
1320 ep
->ino
, ep
->link_set
);
1322 dbprintf("allocated inode %lld "
1323 "has 0 link count\n",
1329 } else if (verbose
|| ep
->ilist
) {
1330 path
= inode_name(ep
->ino
, NULL
);
1332 dbprintf("inode %lld name %s\n",
1345 xfs_agnumber_t agno
,
1346 xfs_agblock_t agbno
,
1351 if (agno
>= mp
->m_sb
.sb_agcount
||
1352 agbno
+ len
- 1 >= mp
->m_sb
.sb_agblocks
) {
1353 for (i
= 0; i
< len
; i
++) {
1354 if (!sflag
|| CHECK_BLISTA(agno
, agbno
+ i
))
1355 dbprintf("block %u/%u out of range\n",
1373 for (i
= 0, p
= &dbmap
[mp
->m_sb
.sb_agcount
][bno
]; i
< len
; i
++, p
++) {
1374 if ((dbm_t
)*p
!= type
) {
1375 if (!sflag
|| CHECK_BLIST(bno
+ i
))
1376 dbprintf("rtblock %llu expected type %s got "
1378 bno
+ i
, typename
[type
],
1379 typename
[(dbm_t
)*p
]);
1395 if (!check_rrange(bno
, len
)) {
1396 dbprintf("rtblocks %llu..%llu claimed by inode %lld\n",
1397 bno
, bno
+ len
- 1, c_ino
);
1400 for (i
= 0, rval
= 1, idp
= &inomap
[mp
->m_sb
.sb_agcount
][bno
];
1404 if (!sflag
|| (*idp
)->ilist
|| CHECK_BLIST(bno
+ i
))
1405 dbprintf("rtblock %llu claimed by inode %lld, "
1406 "previous inum %lld\n",
1407 bno
+ i
, c_ino
, (*idp
)->ino
);
1420 id
= find_inode(mp
->m_sb
.sb_rootino
, 0);
1423 dbprintf("root inode %lld is missing\n",
1424 mp
->m_sb
.sb_rootino
);
1426 } else if (!id
->isdir
) {
1427 if (!sflag
|| id
->ilist
)
1428 dbprintf("root inode %lld is not a directory\n",
1429 mp
->m_sb
.sb_rootino
);
1441 if (bno
+ len
- 1 >= mp
->m_sb
.sb_rblocks
) {
1442 for (i
= 0; i
< len
; i
++) {
1443 if (!sflag
|| CHECK_BLIST(bno
+ i
))
1444 dbprintf("rtblock %llu out of range\n",
1455 xfs_agnumber_t agno
,
1456 xfs_agblock_t agbno
,
1460 xfs_agnumber_t c_agno
,
1461 xfs_agblock_t c_agbno
)
1467 if (!check_range(agno
, agbno
, len
)) {
1468 dbprintf("blocks %u/%u..%u claimed by block %u/%u\n", agno
,
1469 agbno
, agbno
+ len
- 1, c_agno
, c_agbno
);
1472 check_dbmap(agno
, agbno
, len
, type1
);
1473 mayprint
= verbose
| blist_size
;
1474 for (i
= 0, p
= &dbmap
[agno
][agbno
]; i
< len
; i
++, p
++) {
1476 if (mayprint
&& (verbose
|| CHECK_BLISTA(agno
, agbno
+ i
)))
1477 dbprintf("setting block %u/%u to %s\n", agno
, agbno
+ i
,
1493 if (!check_rrange(bno
, len
))
1495 check_rdbmap(bno
, len
, type1
);
1496 mayprint
= verbose
| blist_size
;
1497 for (i
= 0, p
= &dbmap
[mp
->m_sb
.sb_agcount
][bno
]; i
< len
; i
++, p
++) {
1499 if (mayprint
&& (verbose
|| CHECK_BLIST(bno
+ i
)))
1500 dbprintf("setting rtblock %llu to %s\n",
1501 bno
+ i
, typename
[type2
]);
1515 for (log
= 0; log
< mp
->m_rsumlevels
; log
++) {
1517 bno
< mp
->m_sb
.sb_rbmblocks
;
1518 bno
++, csp
++, fsp
++) {
1521 dbprintf("rt summary mismatch, size %d "
1522 "block %llu, file: %d, "
1524 log
, bno
, *fsp
, *csp
);
1533 xfs_agnumber_t agno
,
1534 xfs_agblock_t agbno
,
1541 if (!check_range(agno
, agbno
, len
))
1543 for (i
= 0, p
= &dbmap
[agno
][agbno
]; i
< len
; i
++, p
++) {
1544 if ((1 << *p
) & typemask
) {
1545 if (!sflag
|| CHECK_BLISTA(agno
, agbno
+ i
))
1546 dbprintf("block %u/%u type %s not expected\n",
1547 agno
, agbno
+ i
, typename
[(dbm_t
)*p
]);
1562 if (!check_rrange(bno
, len
))
1564 for (i
= 0, p
= &dbmap
[mp
->m_sb
.sb_agcount
][bno
]; i
< len
; i
++, p
++) {
1565 if ((1 << *p
) & typemask
) {
1566 if (!sflag
|| CHECK_BLIST(bno
+ i
))
1567 dbprintf("rtblock %llu type %s not expected\n",
1568 bno
+ i
, typename
[(dbm_t
)*p
]);
1577 xfs_dir2_dataptr_t addr
)
1582 i
= DIR_HASH_FUNC(hash
, addr
);
1583 p
= malloc(sizeof(*p
));
1584 p
->next
= dirhash
[i
];
1586 p
->entry
.hashval
= hash
;
1587 p
->entry
.address
= addr
;
1599 for (i
= 0; i
< DIR_HASH_SIZE
; i
++) {
1600 for (p
= dirhash
[i
]; p
; p
= p
->next
) {
1603 if (!sflag
|| id
->ilist
|| v
)
1604 dbprintf("dir ino %lld missing leaf entry for "
1606 id
->ino
, p
->entry
.hashval
,
1620 for (i
= 0; i
< DIR_HASH_SIZE
; i
++) {
1621 for (p
= dirhash
[i
]; p
; p
= n
) {
1633 dirhash
= calloc(DIR_HASH_SIZE
, sizeof(*dirhash
));
1639 xfs_dir2_dataptr_t addr
)
1644 i
= DIR_HASH_FUNC(hash
, addr
);
1645 for (p
= dirhash
[i
]; p
; p
= p
->next
) {
1646 if (p
->entry
.hashval
== hash
&& p
->entry
.address
== addr
) {
1662 xfs_agnumber_t agno
;
1667 agno
= XFS_INO_TO_AGNO(mp
, ino
);
1668 agino
= XFS_INO_TO_AGINO(mp
, ino
);
1669 if (agno
>= mp
->m_sb
.sb_agcount
||
1670 XFS_AGINO_TO_INO(mp
, agno
, agino
) != ino
)
1672 htab
= inodata
[agno
];
1673 ih
= agino
% inodata_hash_size
;
1676 if (ent
->ino
== ino
)
1682 ent
= xcalloc(1, sizeof(*ent
));
1684 ent
->next
= htab
[ih
];
1691 xfs_agnumber_t agno
)
1699 for (i
= 0; i
< inodata_hash_size
; i
++) {
1722 if (mp
->m_sb
.sb_magicnum
!= XFS_SB_MAGIC
) {
1723 dbprintf("bad superblock magic number %x, giving up\n",
1724 mp
->m_sb
.sb_magicnum
);
1727 rt
= mp
->m_sb
.sb_rextents
!= 0;
1728 dbmap
= xmalloc((mp
->m_sb
.sb_agcount
+ rt
) * sizeof(*dbmap
));
1729 inomap
= xmalloc((mp
->m_sb
.sb_agcount
+ rt
) * sizeof(*inomap
));
1730 inodata
= xmalloc(mp
->m_sb
.sb_agcount
* sizeof(*inodata
));
1732 (int)MAX(MIN(mp
->m_sb
.sb_icount
/
1733 (INODATA_AVG_HASH_LENGTH
* mp
->m_sb
.sb_agcount
),
1734 MAX_INODATA_HASH_SIZE
),
1735 MIN_INODATA_HASH_SIZE
);
1736 for (c
= 0; c
< mp
->m_sb
.sb_agcount
; c
++) {
1737 dbmap
[c
] = xcalloc(mp
->m_sb
.sb_agblocks
, sizeof(**dbmap
));
1738 inomap
[c
] = xcalloc(mp
->m_sb
.sb_agblocks
, sizeof(**inomap
));
1739 inodata
[c
] = xcalloc(inodata_hash_size
, sizeof(**inodata
));
1742 dbmap
[c
] = xcalloc(mp
->m_sb
.sb_rblocks
, sizeof(**dbmap
));
1743 inomap
[c
] = xcalloc(mp
->m_sb
.sb_rblocks
, sizeof(**inomap
));
1744 sumfile
= xcalloc(mp
->m_rsumsize
, 1);
1745 sumcompute
= xcalloc(mp
->m_rsumsize
, 1);
1747 nflag
= sflag
= verbose
= optind
= 0;
1748 while ((c
= getopt(argc
, argv
, "b:i:npsv")) != EOF
) {
1751 bno
= atoll(optarg
);
1755 ino
= atoll(optarg
);
1771 dbprintf("bad option for blockget command\n");
1775 error
= sbver_err
= serious_error
= 0;
1776 fdblocks
= frextents
= icount
= ifree
= 0;
1777 sbversion
= XFS_SB_VERSION_4
;
1778 if (mp
->m_sb
.sb_inoalignmt
)
1779 sbversion
|= XFS_SB_VERSION_ALIGNBIT
;
1780 if ((mp
->m_sb
.sb_uquotino
&& mp
->m_sb
.sb_uquotino
!= NULLFSINO
) ||
1781 (mp
->m_sb
.sb_pquotino
&& mp
->m_sb
.sb_pquotino
!= NULLFSINO
))
1782 sbversion
|= XFS_SB_VERSION_QUOTABIT
;
1796 id
= find_inode(ino
, 0);
1801 if (id
->name
== NULL
)
1803 path
= xstrdup(id
->name
);
1804 while (id
->parent
) {
1806 if (id
->name
== NULL
)
1808 npath
= prepend_path(path
, id
->name
);
1820 xfs_agnumber_t agno
;
1833 if (!inodata
|| !nflag
) {
1834 dbprintf("must run blockget -n first\n");
1837 security
= optind
= ilist_size
= 0;
1839 while ((c
= getopt(argc
, argv
, "i:s")) != EOF
) {
1842 ino
= atoll(optarg
);
1843 ilist
= xrealloc(ilist
, (ilist_size
+ 1) *
1845 ilist
[ilist_size
++] = ino
;
1851 dbprintf("bad option -%c for ncheck command\n", c
);
1856 for (ilp
= ilist
; ilp
< &ilist
[ilist_size
]; ilp
++) {
1858 if (p
= inode_name(ino
, &hp
)) {
1859 dbprintf("%11llu %s", ino
, p
);
1869 for (agno
= 0; agno
< mp
->m_sb
.sb_agcount
; agno
++) {
1871 for (i
= 0; i
< inodata_hash_size
; i
++) {
1873 for (hp
= ht
[i
]; hp
; hp
= hp
->next
) {
1874 ino
= XFS_AGINO_TO_INO(mp
, agno
, hp
->ino
);
1875 p
= inode_name(ino
, &id
);
1878 if (!security
|| id
->security
) {
1879 dbprintf("%11llu %s", ino
, p
);
1899 len
= (int)(strlen(oldpath
) + strlen(parent
) + 2);
1900 path
= xmalloc(len
);
1901 sprintf(path
, "%s/%s", parent
, oldpath
);
1906 process_block_dir_v2(
1920 nex
= blkmap_getn(blkmap
, 0, mp
->m_dirblkfsbs
, &bmp
);
1921 v
= id
->ilist
|| verbose
;
1924 dbprintf("block 0 for directory inode %lld is "
1932 make_bbmap(&bbmap
, nex
, bmp
);
1933 set_cur(&typtab
[TYP_DIR
], XFS_FSB_TO_DADDR(mp
, bmp
->startblock
),
1934 mp
->m_dirblkfsbs
* blkbb
, DB_RING_IGN
, nex
> 1 ? &bbmap
: NULL
);
1935 for (x
= 0; !v
&& x
< nex
; x
++) {
1936 for (b
= bmp
[x
].startblock
;
1937 !v
&& b
< bmp
[x
].startblock
+ bmp
[x
].blockcount
;
1942 if (iocur_top
->data
== NULL
) {
1943 if (!sflag
|| id
->ilist
|| v
)
1944 dbprintf("can't read block 0 for directory inode "
1951 parent
= process_data_dir_v2(dot
, dotdot
, id
, v
, mp
->m_dirdatablk
,
1953 dir_hash_check(id
, v
);
1960 process_bmbt_reclist(
1961 xfs_bmbt_rec_32_t
*rp
,
1968 xfs_agblock_t agbno
;
1969 xfs_agnumber_t agno
;
1975 xfs_agblock_t iagbno
;
1976 xfs_agnumber_t iagno
;
1983 v
= verbose
|| id
->ilist
;
1984 iagno
= XFS_INO_TO_AGNO(mp
, id
->ino
);
1985 iagbno
= XFS_INO_TO_AGBNO(mp
, id
->ino
);
1986 for (i
= 0; i
< numrecs
; i
++, rp
++) {
1987 convert_extent((xfs_bmbt_rec_64_t
*)rp
, &o
, &s
, &c
, &f
);
1989 dbprintf("inode %lld extent [%lld,%lld,%lld,%d]\n",
1990 id
->ino
, o
, s
, c
, f
);
1991 if (!sflag
&& i
> 0 && op
+ cp
> o
)
1992 dbprintf("bmap rec out of order, inode %lld entry %d\n",
1996 if (type
== DBM_RTDATA
) {
1997 if (!sflag
&& s
>= mp
->m_sb
.sb_rblocks
) {
1998 dbprintf("inode %lld bad rt block number %lld, "
2003 } else if (!sflag
) {
2004 agno
= XFS_FSB_TO_AGNO(mp
, s
);
2005 agbno
= XFS_FSB_TO_AGBNO(mp
, s
);
2006 if (agno
>= mp
->m_sb
.sb_agcount
||
2007 agbno
>= mp
->m_sb
.sb_agblocks
) {
2008 dbprintf("inode %lld bad block number %lld "
2009 "[%d,%d], offset %lld\n",
2010 id
->ino
, s
, agno
, agbno
, o
);
2013 if (agbno
+ c
- 1 >= mp
->m_sb
.sb_agblocks
) {
2014 dbprintf("inode %lld bad block number %lld "
2015 "[%d,%d], offset %lld\n",
2016 id
->ino
, s
+ c
- 1, agno
,
2017 agbno
+ (xfs_agblock_t
)c
- 1, o
);
2021 if (blkmapp
&& *blkmapp
)
2022 blkmap_set_ext(blkmapp
, (xfs_fileoff_t
)o
,
2023 (xfs_fsblock_t
)s
, (xfs_extlen_t
)c
);
2024 if (type
== DBM_RTDATA
) {
2025 set_rdbmap((xfs_fsblock_t
)s
, (xfs_extlen_t
)c
,
2027 set_rinomap((xfs_fsblock_t
)s
, (xfs_extlen_t
)c
, id
);
2028 for (b
= (xfs_fsblock_t
)s
;
2029 blist_size
&& b
< s
+ c
;
2032 dbprintf("inode %lld block %lld at "
2034 id
->ino
, (xfs_dfsbno_t
)b
, o
);
2037 agno
= XFS_FSB_TO_AGNO(mp
, (xfs_fsblock_t
)s
);
2038 agbno
= XFS_FSB_TO_AGBNO(mp
, (xfs_fsblock_t
)s
);
2039 set_dbmap(agno
, agbno
, (xfs_extlen_t
)c
, type
, iagno
,
2041 set_inomap(agno
, agbno
, (xfs_extlen_t
)c
, id
);
2042 for (b
= (xfs_fsblock_t
)s
;
2043 blist_size
&& b
< s
+ c
;
2044 b
++, o
++, agbno
++) {
2046 dbprintf("inode %lld block %lld at "
2048 id
->ino
, (xfs_dfsbno_t
)b
, o
);
2060 xfs_drfsbno_t
*totd
,
2061 xfs_drfsbno_t
*toti
,
2066 xfs_bmdr_block_t
*dib
;
2069 xfs_bmbt_rec_32_t
*rp
;
2071 dib
= (xfs_bmdr_block_t
*)XFS_DFORK_PTR_ARCH(dip
, whichfork
, ARCH_NOCONVERT
);
2072 if (INT_GET(dib
->bb_level
, ARCH_CONVERT
) >= XFS_BM_MAXLEVELS(mp
, whichfork
)) {
2073 if (!sflag
|| id
->ilist
)
2074 dbprintf("level for ino %lld %s fork bmap root too "
2077 whichfork
== XFS_DATA_FORK
? "data" : "attr",
2078 INT_GET(dib
->bb_level
, ARCH_CONVERT
));
2082 if (INT_GET(dib
->bb_numrecs
, ARCH_CONVERT
) >
2083 XFS_BTREE_BLOCK_MAXRECS(XFS_DFORK_SIZE_ARCH(dip
, mp
, whichfork
, ARCH_NOCONVERT
),
2084 xfs_bmdr
, INT_GET(dib
->bb_level
, ARCH_CONVERT
) == 0)) {
2085 if (!sflag
|| id
->ilist
)
2086 dbprintf("numrecs for ino %lld %s fork bmap root too "
2089 whichfork
== XFS_DATA_FORK
? "data" : "attr",
2090 INT_GET(dib
->bb_numrecs
, ARCH_CONVERT
));
2094 if (INT_GET(dib
->bb_level
, ARCH_CONVERT
) == 0) {
2095 rp
= (xfs_bmbt_rec_32_t
*)XFS_BTREE_REC_ADDR(
2096 XFS_DFORK_SIZE_ARCH(dip
, mp
, whichfork
, ARCH_NOCONVERT
),
2098 XFS_BTREE_BLOCK_MAXRECS(XFS_DFORK_SIZE(dip
, mp
,
2101 process_bmbt_reclist(rp
, INT_GET(dib
->bb_numrecs
, ARCH_CONVERT
), type
, id
, totd
,
2103 *nex
+= INT_GET(dib
->bb_numrecs
, ARCH_CONVERT
);
2106 pp
= XFS_BTREE_PTR_ADDR(XFS_DFORK_SIZE_ARCH(dip
, mp
, whichfork
, ARCH_NOCONVERT
),
2108 XFS_BTREE_BLOCK_MAXRECS(XFS_DFORK_SIZE(dip
, mp
,
2111 for (i
= 0; i
< INT_GET(dib
->bb_numrecs
, ARCH_CONVERT
); i
++)
2112 scan_lbtree((xfs_fsblock_t
)INT_GET(pp
[i
], ARCH_CONVERT
), INT_GET(dib
->bb_level
, ARCH_CONVERT
),
2113 scanfunc_bmap
, type
, id
, totd
, toti
, nex
,
2115 whichfork
== XFS_DATA_FORK
?
2116 TYP_BMAPBTD
: TYP_BMAPBTA
);
2119 XFS_DFORK_SIZE_ARCH(dip
, mp
, whichfork
, ARCH_NOCONVERT
) / sizeof(xfs_bmbt_rec_t
)) {
2120 if (!sflag
|| id
->ilist
)
2121 dbprintf("extent count for ino %lld %s fork too low "
2122 "(%d) for file format\n",
2124 whichfork
== XFS_DATA_FORK
? "data" : "attr",
2131 process_data_dir_v2(
2137 freetab_t
**freetabp
)
2139 xfs_dir2_dataptr_t addr
;
2140 xfs_dir2_data_free_t
*bf
;
2142 xfs_dir2_block_t
*block
;
2143 xfs_dir2_block_tail_t
*btp
= NULL
;
2146 xfs_dir2_data_t
*data
;
2148 xfs_dir2_data_entry_t
*dep
;
2149 xfs_dir2_data_free_t
*dfp
;
2150 xfs_dir2_data_unused_t
*dup
;
2158 xfs_dir2_leaf_entry_t
*lep
= NULL
;
2160 xfs_ino_t parent
= 0;
2164 xfs_dir2_data_off_t
*tagp
;
2166 data
= iocur_top
->data
;
2167 block
= iocur_top
->data
;
2168 if (INT_GET(block
->hdr
.magic
, ARCH_CONVERT
) != XFS_DIR2_BLOCK_MAGIC
&&
2169 INT_GET(data
->hdr
.magic
, ARCH_CONVERT
) != XFS_DIR2_DATA_MAGIC
) {
2171 dbprintf("bad directory data magic # %#x for dir ino "
2173 INT_GET(data
->hdr
.magic
, ARCH_CONVERT
), id
->ino
, dabno
);
2177 db
= XFS_DIR2_DA_TO_DB(mp
, dabno
);
2178 bf
= data
->hdr
.bestfree
;
2179 ptr
= (char *)data
->u
;
2180 if (INT_GET(block
->hdr
.magic
, ARCH_CONVERT
) == XFS_DIR2_BLOCK_MAGIC
) {
2181 btp
= XFS_DIR2_BLOCK_TAIL_P(mp
, block
);
2182 lep
= XFS_DIR2_BLOCK_LEAF_P_ARCH(btp
, ARCH_CONVERT
);
2183 endptr
= (char *)lep
;
2184 if (endptr
<= ptr
|| endptr
> (char *)btp
) {
2185 endptr
= (char *)data
+ mp
->m_dirblksize
;
2188 dbprintf("bad block directory tail for dir ino "
2194 endptr
= (char *)data
+ mp
->m_dirblksize
;
2195 bf_err
= lastfree_err
= tag_err
= 0;
2196 count
= lastfree
= freeseen
= 0;
2197 if (INT_GET(bf
[0].length
, ARCH_CONVERT
) == 0) {
2198 bf_err
+= INT_GET(bf
[0].offset
, ARCH_CONVERT
) != 0;
2201 if (INT_GET(bf
[1].length
, ARCH_CONVERT
) == 0) {
2202 bf_err
+= INT_GET(bf
[1].offset
, ARCH_CONVERT
) != 0;
2205 if (INT_GET(bf
[2].length
, ARCH_CONVERT
) == 0) {
2206 bf_err
+= INT_GET(bf
[2].offset
, ARCH_CONVERT
) != 0;
2209 bf_err
+= INT_GET(bf
[0].length
, ARCH_CONVERT
) < INT_GET(bf
[1].length
, ARCH_CONVERT
);
2210 bf_err
+= INT_GET(bf
[1].length
, ARCH_CONVERT
) < INT_GET(bf
[2].length
, ARCH_CONVERT
);
2212 freetab
= *freetabp
;
2213 if (freetab
->naents
<= db
) {
2214 *freetabp
= freetab
=
2215 realloc(freetab
, FREETAB_SIZE(db
+ 1));
2216 for (i
= freetab
->naents
; i
< db
; i
++)
2217 freetab
->ents
[i
] = NULLDATAOFF
;
2218 freetab
->naents
= db
+ 1;
2220 if (freetab
->nents
< db
+ 1)
2221 freetab
->nents
= db
+ 1;
2222 freetab
->ents
[db
] = INT_GET(bf
[0].length
, ARCH_CONVERT
);
2224 while (ptr
< endptr
) {
2225 dup
= (xfs_dir2_data_unused_t
*)ptr
;
2226 if (INT_GET(dup
->freetag
, ARCH_CONVERT
) == XFS_DIR2_DATA_FREE_TAG
) {
2227 lastfree_err
+= lastfree
!= 0;
2228 if ((INT_GET(dup
->length
, ARCH_CONVERT
) & (XFS_DIR2_DATA_ALIGN
- 1)) ||
2229 INT_GET(dup
->length
, ARCH_CONVERT
) == 0 ||
2230 (char *)(tagp
= XFS_DIR2_DATA_UNUSED_TAG_P_ARCH(dup
, ARCH_CONVERT
)) >=
2233 dbprintf("dir %lld block %d bad free "
2241 tag_err
+= INT_GET(*tagp
, ARCH_CONVERT
) != (char *)dup
- (char *)data
;
2242 dfp
= process_data_dir_v2_freefind(data
, dup
);
2244 i
= (int)(dfp
- bf
);
2245 bf_err
+= (freeseen
& (1 << i
)) != 0;
2248 bf_err
+= INT_GET(dup
->length
, ARCH_CONVERT
) > INT_GET(bf
[2].length
, ARCH_CONVERT
);
2249 ptr
+= INT_GET(dup
->length
, ARCH_CONVERT
);
2253 dep
= (xfs_dir2_data_entry_t
*)dup
;
2254 if (dep
->namelen
== 0) {
2256 dbprintf("dir %lld block %d zero length entry "
2259 (int)((char *)dep
- (char *)data
));
2262 tagp
= XFS_DIR2_DATA_ENTRY_TAG_P(dep
);
2263 if ((char *)tagp
>= endptr
) {
2265 dbprintf("dir %lld block %d bad entry at %d\n",
2267 (int)((char *)dep
- (char *)data
));
2271 tag_err
+= INT_GET(*tagp
, ARCH_CONVERT
) != (char *)dep
- (char *)data
;
2272 addr
= XFS_DIR2_DB_OFF_TO_DATAPTR(mp
, db
,
2273 (char *)dep
- (char *)data
);
2274 hash
= libxfs_da_hashname((char *)dep
->name
, dep
->namelen
);
2275 dir_hash_add(hash
, addr
);
2276 ptr
+= XFS_DIR2_DATA_ENTSIZE(dep
->namelen
);
2279 lino
= INT_GET(dep
->inumber
, ARCH_CONVERT
);
2280 cid
= find_inode(lino
, 1);
2282 dbprintf("dir %lld block %d entry %*.*s %lld\n",
2283 id
->ino
, dabno
, dep
->namelen
, dep
->namelen
,
2289 dbprintf("dir %lld block %d entry %*.*s bad "
2290 "inode number %lld\n",
2291 id
->ino
, dabno
, dep
->namelen
,
2292 dep
->namelen
, dep
->name
, lino
);
2295 if (dep
->namelen
== 2 && dep
->name
[0] == '.' &&
2296 dep
->name
[1] == '.') {
2299 dbprintf("multiple .. entries in dir "
2300 "%lld (%lld, %lld)\n",
2301 id
->ino
, parent
, lino
);
2304 parent
= cid
? lino
: NULLFSINO
;
2306 } else if (dep
->namelen
!= 1 || dep
->name
[0] != '.') {
2310 addname_inode(cid
, (char *)dep
->name
,
2314 if (lino
!= id
->ino
) {
2316 dbprintf("dir %lld entry . inode "
2317 "number mismatch (%lld)\n",
2324 if (INT_GET(data
->hdr
.magic
, ARCH_CONVERT
) == XFS_DIR2_BLOCK_MAGIC
) {
2325 endptr
= (char *)data
+ mp
->m_dirblksize
;
2326 for (i
= stale
= 0; lep
&& i
< INT_GET(btp
->count
, ARCH_CONVERT
); i
++) {
2327 if ((char *)&lep
[i
] >= endptr
) {
2329 dbprintf("dir %lld block %d bad count "
2331 id
->ino
, dabno
, INT_GET(btp
->count
, ARCH_CONVERT
));
2335 if (INT_GET(lep
[i
].address
, ARCH_CONVERT
) == XFS_DIR2_NULL_DATAPTR
)
2337 else if (dir_hash_see(INT_GET(lep
[i
].hashval
, ARCH_CONVERT
), INT_GET(lep
[i
].address
, ARCH_CONVERT
))) {
2339 dbprintf("dir %lld block %d extra leaf "
2341 id
->ino
, dabno
, INT_GET(lep
[i
].hashval
, ARCH_CONVERT
),
2342 INT_GET(lep
[i
].address
, ARCH_CONVERT
));
2347 bf_err
+= freeseen
!= 7;
2350 dbprintf("dir %lld block %d bad bestfree data\n",
2354 if (INT_GET(data
->hdr
.magic
, ARCH_CONVERT
) == XFS_DIR2_BLOCK_MAGIC
&&
2355 count
!= INT_GET(btp
->count
, ARCH_CONVERT
) - INT_GET(btp
->stale
, ARCH_CONVERT
)) {
2357 dbprintf("dir %lld block %d bad block tail count %d "
2359 id
->ino
, dabno
, INT_GET(btp
->count
, ARCH_CONVERT
), INT_GET(btp
->stale
, ARCH_CONVERT
));
2362 if (INT_GET(data
->hdr
.magic
, ARCH_CONVERT
) == XFS_DIR2_BLOCK_MAGIC
&& stale
!= INT_GET(btp
->stale
, ARCH_CONVERT
)) {
2364 dbprintf("dir %lld block %d bad stale tail count %d\n",
2365 id
->ino
, dabno
, INT_GET(btp
->stale
, ARCH_CONVERT
));
2370 dbprintf("dir %lld block %d consecutive free entries\n",
2376 dbprintf("dir %lld block %d entry/unused tag "
2384 static xfs_dir2_data_free_t
*
2385 process_data_dir_v2_freefind(
2386 xfs_dir2_data_t
*data
,
2387 xfs_dir2_data_unused_t
*dup
)
2389 xfs_dir2_data_free_t
*dfp
;
2390 xfs_dir2_data_aoff_t off
;
2392 off
= (xfs_dir2_data_aoff_t
)((char *)dup
- (char *)data
);
2393 if (INT_GET(dup
->length
, ARCH_CONVERT
) < INT_GET(data
->hdr
.bestfree
[XFS_DIR2_DATA_FD_COUNT
- 1].length
, ARCH_CONVERT
))
2395 for (dfp
= &data
->hdr
.bestfree
[0];
2396 dfp
< &data
->hdr
.bestfree
[XFS_DIR2_DATA_FD_COUNT
];
2398 if (INT_GET(dfp
->offset
, ARCH_CONVERT
) == 0)
2400 if (INT_GET(dfp
->offset
, ARCH_CONVERT
) == off
)
2418 if (XFS_DIR_IS_V2(mp
)) {
2419 if (process_dir_v2(dip
, blkmap
, &dot
, &dotdot
, id
, &parent
))
2423 if (process_dir_v1(dip
, blkmap
, &dot
, &dotdot
, id
, &parent
))
2426 bno
= XFS_INO_TO_FSB(mp
, id
->ino
);
2428 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2429 dbprintf("no . entry for directory %lld\n", id
->ino
);
2433 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2434 dbprintf("no .. entry for directory %lld\n", id
->ino
);
2436 } else if (parent
== id
->ino
&& id
->ino
!= mp
->m_sb
.sb_rootino
) {
2437 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2438 dbprintf(". and .. same for non-root directory %lld\n",
2441 } else if (id
->ino
== mp
->m_sb
.sb_rootino
&& id
->ino
!= parent
) {
2442 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2443 dbprintf("root directory %lld has .. %lld\n", id
->ino
,
2446 } else if (parent
!= NULLFSINO
&& id
->ino
!= parent
)
2447 addparent_inode(id
, parent
);
2459 if (dip
->di_core
.di_size
<= XFS_DFORK_DSIZE_ARCH(dip
, mp
, ARCH_NOCONVERT
) &&
2460 dip
->di_core
.di_format
== XFS_DINODE_FMT_LOCAL
)
2462 process_shortform_dir_v1(dip
, dot
, dotdot
, id
);
2463 else if (dip
->di_core
.di_size
== XFS_LBSIZE(mp
) &&
2464 (dip
->di_core
.di_format
== XFS_DINODE_FMT_EXTENTS
||
2465 dip
->di_core
.di_format
== XFS_DINODE_FMT_BTREE
))
2466 *parent
= process_leaf_dir_v1(blkmap
, dot
, dotdot
, id
);
2467 else if (dip
->di_core
.di_size
>= XFS_LBSIZE(mp
) &&
2468 (dip
->di_core
.di_format
== XFS_DINODE_FMT_EXTENTS
||
2469 dip
->di_core
.di_format
== XFS_DINODE_FMT_BTREE
))
2470 *parent
= process_node_dir_v1(blkmap
, dot
, dotdot
, id
);
2472 dbprintf("bad size (%lld) or format (%d) for directory inode "
2474 dip
->di_core
.di_size
, (int)dip
->di_core
.di_format
,
2491 xfs_fileoff_t last
= 0;
2494 last
= blkmap_last_off(blkmap
);
2495 if (dip
->di_core
.di_size
<= XFS_DFORK_DSIZE_ARCH(dip
, mp
, ARCH_NOCONVERT
) &&
2496 dip
->di_core
.di_format
== XFS_DINODE_FMT_LOCAL
)
2497 *parent
= process_sf_dir_v2(dip
, dot
, dotdot
, id
);
2498 else if (last
== mp
->m_dirblkfsbs
&&
2499 (dip
->di_core
.di_format
== XFS_DINODE_FMT_EXTENTS
||
2500 dip
->di_core
.di_format
== XFS_DINODE_FMT_BTREE
))
2501 *parent
= process_block_dir_v2(blkmap
, dot
, dotdot
, id
);
2502 else if (last
>= mp
->m_dirleafblk
+ mp
->m_dirblkfsbs
&&
2503 (dip
->di_core
.di_format
== XFS_DINODE_FMT_EXTENTS
||
2504 dip
->di_core
.di_format
== XFS_DINODE_FMT_BTREE
))
2505 *parent
= process_leaf_node_dir_v2(blkmap
, dot
, dotdot
, id
,
2506 dip
->di_core
.di_size
);
2508 dbprintf("bad size (%lld) or format (%d) for directory inode "
2510 dip
->di_core
.di_size
, (int)dip
->di_core
.di_format
,
2524 xfs_drfsbno_t
*totd
,
2525 xfs_drfsbno_t
*toti
,
2530 xfs_bmbt_rec_32_t
*rp
;
2532 rp
= (xfs_bmbt_rec_32_t
*)XFS_DFORK_PTR_ARCH(dip
, whichfork
, ARCH_NOCONVERT
);
2533 *nex
= XFS_DFORK_NEXTENTS_ARCH(dip
, whichfork
, ARCH_NOCONVERT
);
2536 XFS_DFORK_SIZE_ARCH(dip
, mp
, whichfork
, ARCH_NOCONVERT
) / sizeof(xfs_bmbt_rec_32_t
)) {
2537 if (!sflag
|| id
->ilist
)
2538 dbprintf("bad number of extents %d for inode %lld\n",
2543 process_bmbt_reclist(rp
, *nex
, type
, id
, totd
, blkmapp
);
2554 xfs_fsblock_t bno
= 0;
2555 xfs_dinode_core_t tdic
;
2556 xfs_dinode_core_t
*dic
;
2557 inodata_t
*id
= NULL
;
2559 xfs_extnum_t nextents
= 0;
2562 xfs_drfsbno_t totblocks
;
2563 xfs_drfsbno_t totdblocks
= 0;
2564 xfs_drfsbno_t totiblocks
= 0;
2566 xfs_extnum_t anextents
= 0;
2567 xfs_drfsbno_t atotdblocks
= 0;
2568 xfs_drfsbno_t atotiblocks
= 0;
2572 static char okfmts
[] = {
2573 0, /* type 0 unused */
2574 1 << XFS_DINODE_FMT_DEV
, /* FIFO */
2575 1 << XFS_DINODE_FMT_DEV
, /* CHR */
2576 0, /* type 3 unused */
2577 (1 << XFS_DINODE_FMT_LOCAL
) |
2578 (1 << XFS_DINODE_FMT_EXTENTS
) |
2579 (1 << XFS_DINODE_FMT_BTREE
), /* DIR */
2580 0, /* type 5 unused */
2581 1 << XFS_DINODE_FMT_DEV
, /* BLK */
2582 0, /* type 7 unused */
2583 (1 << XFS_DINODE_FMT_EXTENTS
) |
2584 (1 << XFS_DINODE_FMT_BTREE
), /* REG */
2585 0, /* type 9 unused */
2586 (1 << XFS_DINODE_FMT_LOCAL
) |
2587 (1 << XFS_DINODE_FMT_EXTENTS
), /* LNK */
2588 0, /* type 11 unused */
2589 1 << XFS_DINODE_FMT_DEV
, /* SOCK */
2590 0, /* type 13 unused */
2591 1 << XFS_DINODE_FMT_UUID
, /* MNT */
2592 0 /* type 15 unused */
2594 static char *fmtnames
[] = {
2595 "dev", "local", "extents", "btree", "uuid"
2598 /* convert the core, then copy it back into the inode */
2599 libxfs_xlate_dinode_core((xfs_caddr_t
)&dip
->di_core
, &tdic
, 1,
2601 memcpy(&dip
->di_core
, &tdic
, sizeof(xfs_dinode_core_t
));
2604 ino
= XFS_AGINO_TO_INO(mp
, INT_GET(agf
->agf_seqno
, ARCH_CONVERT
), agino
);
2606 id
= find_inode(ino
, 1);
2607 bno
= XFS_INO_TO_FSB(mp
, ino
);
2610 if (dic
->di_magic
!= XFS_DINODE_MAGIC
) {
2611 if (!sflag
|| isfree
|| id
->ilist
|| CHECK_BLIST(bno
))
2612 dbprintf("bad magic number %#x for inode %lld\n",
2613 dic
->di_magic
, ino
);
2617 if (!XFS_DINODE_GOOD_VERSION(dic
->di_version
)) {
2618 if (!sflag
|| isfree
|| id
->ilist
|| CHECK_BLIST(bno
))
2619 dbprintf("bad version number %#x for inode %lld\n",
2620 dic
->di_version
, ino
);
2625 if (dic
->di_nblocks
!= 0) {
2626 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2627 dbprintf("bad nblocks %lld for free inode "
2629 dic
->di_nblocks
, ino
);
2632 if (dic
->di_version
== XFS_DINODE_VERSION_1
)
2633 nlink
= dic
->di_onlink
;
2635 nlink
= dic
->di_nlink
;
2637 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2638 dbprintf("bad nlink %d for free inode %lld\n",
2642 if (dic
->di_mode
!= 0) {
2643 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2644 dbprintf("bad mode %#o for free inode %lld\n",
2651 * di_mode is a 16-bit uint so no need to check the < 0 case
2653 if ((((dic
->di_mode
& IFMT
) >> 12) > 15) ||
2654 (!(okfmts
[(dic
->di_mode
& IFMT
) >> 12] & (1 << dic
->di_format
)))) {
2655 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2656 dbprintf("bad format %d for inode %lld type %#o\n",
2657 dic
->di_format
, id
->ino
, dic
->di_mode
& IFMT
);
2661 if ((unsigned int)XFS_DFORK_ASIZE_ARCH(dip
, mp
, ARCH_NOCONVERT
) >= XFS_LITINO(mp
)) {
2662 if (!sflag
|| id
->ilist
)
2663 dbprintf("bad fork offset %d for inode %lld\n",
2664 dic
->di_forkoff
, id
->ino
);
2668 if ((unsigned int)dic
->di_aformat
> XFS_DINODE_FMT_BTREE
) {
2669 if (!sflag
|| id
->ilist
)
2670 dbprintf("bad attribute format %d for inode %lld\n",
2671 dic
->di_aformat
, id
->ino
);
2675 if (verbose
|| id
->ilist
|| CHECK_BLIST(bno
))
2676 dbprintf("inode %lld mode %#o fmt %s "
2678 "nex %d anex %d nblk %lld sz %lld%s%s\n",
2679 id
->ino
, dic
->di_mode
, fmtnames
[dic
->di_format
],
2680 fmtnames
[dic
->di_aformat
],
2683 dic
->di_nblocks
, dic
->di_size
,
2684 dic
->di_flags
& XFS_DIFLAG_REALTIME
? " rt" : "",
2685 dic
->di_flags
& XFS_DIFLAG_PREALLOC
? " pre" : ""
2688 switch (dic
->di_mode
& IFMT
) {
2691 if (dic
->di_format
== XFS_DINODE_FMT_LOCAL
)
2693 blkmap
= blkmap_alloc(dic
->di_nextents
);
2696 if (dic
->di_flags
& XFS_DIFLAG_REALTIME
)
2698 else if (id
->ino
== mp
->m_sb
.sb_rbmino
) {
2699 type
= DBM_RTBITMAP
;
2700 blkmap
= blkmap_alloc(dic
->di_nextents
);
2702 } else if (id
->ino
== mp
->m_sb
.sb_rsumino
) {
2704 blkmap
= blkmap_alloc(dic
->di_nextents
);
2707 else if (id
->ino
== mp
->m_sb
.sb_uquotino
||
2708 id
->ino
== mp
->m_sb
.sb_pquotino
) {
2710 blkmap
= blkmap_alloc(dic
->di_nextents
);
2715 if (dic
->di_mode
& (ISUID
| ISGID
))
2726 if (dic
->di_version
== XFS_DINODE_VERSION_1
)
2727 setlink_inode(id
, dic
->di_onlink
, type
== DBM_DIR
, security
);
2729 sbversion
|= XFS_SB_VERSION_NLINKBIT
;
2730 setlink_inode(id
, dic
->di_nlink
, type
== DBM_DIR
, security
);
2732 switch (dic
->di_format
) {
2733 case XFS_DINODE_FMT_LOCAL
:
2734 process_lclinode(id
, dip
, type
, &totdblocks
, &totiblocks
,
2735 &nextents
, &blkmap
, XFS_DATA_FORK
);
2737 case XFS_DINODE_FMT_EXTENTS
:
2738 process_exinode(id
, dip
, type
, &totdblocks
, &totiblocks
,
2739 &nextents
, &blkmap
, XFS_DATA_FORK
);
2741 case XFS_DINODE_FMT_BTREE
:
2742 process_btinode(id
, dip
, type
, &totdblocks
, &totiblocks
,
2743 &nextents
, &blkmap
, XFS_DATA_FORK
);
2746 if (XFS_DFORK_Q_ARCH(dip
, ARCH_NOCONVERT
)) {
2747 sbversion
|= XFS_SB_VERSION_ATTRBIT
;
2748 switch (dic
->di_aformat
) {
2749 case XFS_DINODE_FMT_LOCAL
:
2750 process_lclinode(id
, dip
, DBM_ATTR
, &atotdblocks
,
2751 &atotiblocks
, &anextents
, NULL
, XFS_ATTR_FORK
);
2753 case XFS_DINODE_FMT_EXTENTS
:
2754 process_exinode(id
, dip
, DBM_ATTR
, &atotdblocks
,
2755 &atotiblocks
, &anextents
, NULL
, XFS_ATTR_FORK
);
2757 case XFS_DINODE_FMT_BTREE
:
2758 process_btinode(id
, dip
, DBM_ATTR
, &atotdblocks
,
2759 &atotiblocks
, &anextents
, NULL
, XFS_ATTR_FORK
);
2771 bc
= totdblocks
+ totiblocks
+
2772 atotdblocks
+ atotiblocks
;
2776 bc
= totiblocks
+ atotdblocks
+ atotiblocks
;
2783 quota_add(dic
->di_version
>= XFS_DINODE_VERSION_2
?
2784 dic
->di_projid
: -1,
2785 dic
->di_uid
, 0, bc
, ic
, rc
);
2787 totblocks
= totdblocks
+ totiblocks
+ atotdblocks
+ atotiblocks
;
2788 if (totblocks
!= dic
->di_nblocks
) {
2789 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2790 dbprintf("bad nblocks %lld for inode %lld, counted "
2792 dic
->di_nblocks
, id
->ino
, totblocks
);
2795 if (nextents
!= dic
->di_nextents
) {
2796 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2797 dbprintf("bad nextents %d for inode %lld, counted %d\n",
2798 dic
->di_nextents
, id
->ino
, nextents
);
2801 if (anextents
!= dic
->di_anextents
) {
2802 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2803 dbprintf("bad anextents %d for inode %lld, counted "
2805 dic
->di_anextents
, id
->ino
, anextents
);
2808 if (type
== DBM_DIR
)
2809 process_dir(dip
, blkmap
, id
);
2810 else if (type
== DBM_RTBITMAP
)
2811 process_rtbitmap(blkmap
);
2812 else if (type
== DBM_RTSUM
)
2813 process_rtsummary(blkmap
);
2815 * If the CHKD flag is not set, this can legitimately contain garbage;
2816 * xfs_repair may have cleared that bit.
2818 else if (type
== DBM_QUOTA
&& (mp
->m_sb
.sb_qflags
& XFS_UQUOTA_CHKD
))
2819 process_quota(id
->ino
== mp
->m_sb
.sb_pquotino
, id
, blkmap
);
2821 blkmap_free(blkmap
);
2830 xfs_drfsbno_t
*totd
,
2831 xfs_drfsbno_t
*toti
,
2836 xfs_attr_shortform_t
*asf
;
2838 xfs_dinode_core_t
*dic
;
2840 dic
= &dip
->di_core
;
2841 bno
= XFS_INO_TO_FSB(mp
, id
->ino
);
2842 if (whichfork
== XFS_DATA_FORK
&&
2843 dic
->di_size
> XFS_DFORK_DSIZE_ARCH(dip
, mp
, ARCH_NOCONVERT
)) {
2844 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2845 dbprintf("local inode %lld data is too large (size "
2847 id
->ino
, dic
->di_size
);
2850 else if (whichfork
== XFS_ATTR_FORK
) {
2851 asf
= (xfs_attr_shortform_t
*)XFS_DFORK_PTR_ARCH(dip
, whichfork
, ARCH_NOCONVERT
);
2852 if (INT_GET(asf
->hdr
.totsize
, ARCH_CONVERT
) > XFS_DFORK_ASIZE_ARCH(dip
, mp
, ARCH_NOCONVERT
)) {
2853 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2854 dbprintf("local inode %lld attr is too large "
2856 id
->ino
, INT_GET(asf
->hdr
.totsize
, ARCH_CONVERT
));
2863 process_leaf_dir_v1(
2872 bno
= blkmap_get(blkmap
, 0);
2873 if (bno
== NULLFSBLOCK
) {
2874 if (!sflag
|| id
->ilist
)
2875 dbprintf("block 0 for directory inode %lld is "
2882 set_cur(&typtab
[TYP_DIR
], XFS_FSB_TO_DADDR(mp
, bno
), blkbb
, DB_RING_IGN
,
2884 if (iocur_top
->data
== NULL
) {
2885 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2886 dbprintf("can't read block 0 for directory inode "
2892 parent
= process_leaf_dir_v1_int(dot
, dotdot
, id
);
2898 process_leaf_dir_v1_int(
2905 xfs_dir_leaf_entry_t
*entry
;
2907 xfs_dir_leafblock_t
*leaf
;
2909 xfs_dir_leaf_name_t
*namest
;
2910 xfs_ino_t parent
= 0;
2913 bno
= XFS_DADDR_TO_FSB(mp
, iocur_top
->bb
);
2914 v
= verbose
|| id
->ilist
|| CHECK_BLIST(bno
);
2915 leaf
= iocur_top
->data
;
2916 if (INT_GET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
) != XFS_DIR_LEAF_MAGIC
) {
2917 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2918 dbprintf("bad directory leaf magic # %#x for dir ino "
2920 INT_GET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
), id
->ino
);
2924 entry
= &leaf
->entries
[0];
2925 for (i
= 0; i
< INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
); entry
++, i
++) {
2926 namest
= XFS_DIR_LEAF_NAMESTRUCT(leaf
, INT_GET(entry
->nameidx
, ARCH_CONVERT
));
2927 lino
=DIRINO_GET_ARCH(&namest
->inumber
, ARCH_CONVERT
);
2928 cid
= find_inode(lino
, 1);
2930 dbprintf("dir %lld entry %*.*s %lld\n", id
->ino
,
2931 entry
->namelen
, entry
->namelen
, namest
->name
,
2937 dbprintf("dir %lld entry %*.*s bad inode "
2939 id
->ino
, entry
->namelen
, entry
->namelen
,
2940 namest
->name
, lino
);
2943 if (entry
->namelen
== 2 && namest
->name
[0] == '.' &&
2944 namest
->name
[1] == '.') {
2946 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2947 dbprintf("multiple .. entries in dir "
2948 "%lld (%lld, %lld)\n",
2949 id
->ino
, parent
, lino
);
2952 parent
= cid
? lino
: NULLFSINO
;
2954 } else if (entry
->namelen
!= 1 || namest
->name
[0] != '.') {
2958 addname_inode(cid
, (char *)namest
->name
,
2962 if (lino
!= id
->ino
) {
2964 dbprintf("dir %lld entry . inode "
2965 "number mismatch (%lld)\n",
2976 process_leaf_node_dir_v2(
2981 xfs_fsize_t dirsize
)
2997 v2
= verbose
|| id
->ilist
;
3000 freetab
= malloc(FREETAB_SIZE(dirsize
/ mp
->m_dirblksize
));
3001 freetab
->naents
= (int)(dirsize
/ mp
->m_dirblksize
);
3003 for (i
= 0; i
< freetab
->naents
; i
++)
3004 freetab
->ents
[i
] = NULLDATAOFF
;
3006 while ((dbno
= blkmap_next_off(blkmap
, dbno
, &t
)) != NULLFILEOFF
) {
3007 nex
= blkmap_getn(blkmap
, dbno
, mp
->m_dirblkfsbs
, &bmp
);
3009 for (v
= v2
, x
= 0; !v
&& x
< nex
; x
++) {
3010 for (b
= bmp
[x
].startblock
;
3011 !v
&& b
< bmp
[x
].startblock
+ bmp
[x
].blockcount
;
3016 dbprintf("dir inode %lld block %u=%llu\n", id
->ino
,
3018 (xfs_dfsbno_t
)bmp
->startblock
);
3021 make_bbmap(&bbmap
, nex
, bmp
);
3022 set_cur(&typtab
[TYP_DIR
], XFS_FSB_TO_DADDR(mp
, bmp
->startblock
),
3023 mp
->m_dirblkfsbs
* blkbb
, DB_RING_IGN
,
3024 nex
> 1 ? &bbmap
: NULL
);
3026 if (iocur_top
->data
== NULL
) {
3028 dbprintf("can't read block %u for directory "
3030 (__uint32_t
)dbno
, id
->ino
);
3033 dbno
+= mp
->m_dirblkfsbs
- 1;
3036 if (dbno
< mp
->m_dirleafblk
) {
3037 lino
= process_data_dir_v2(dot
, dotdot
, id
, v
,
3038 (xfs_dablk_t
)dbno
, &freetab
);
3042 dbprintf("multiple .. entries "
3049 } else if (dbno
< mp
->m_dirfreeblk
) {
3050 process_leaf_node_dir_v2_int(id
, v
, (xfs_dablk_t
)dbno
,
3053 process_leaf_node_dir_v2_free(id
, v
, (xfs_dablk_t
)dbno
,
3057 dbno
+= mp
->m_dirblkfsbs
- 1;
3059 dir_hash_check(id
, v
);
3061 for (i
= 0; i
< freetab
->nents
; i
++) {
3062 if (freetab
->ents
[i
] != NULLDATAOFF
) {
3064 dbprintf("missing free index for data block %d "
3065 "in dir ino %lld\n",
3066 XFS_DIR2_DB_TO_DA(mp
, i
), id
->ino
);
3075 process_leaf_node_dir_v2_free(
3081 xfs_dir2_data_off_t ent
;
3082 xfs_dir2_free_t
*free
;
3087 free
= iocur_top
->data
;
3088 if (INT_GET(free
->hdr
.magic
, ARCH_CONVERT
) != XFS_DIR2_FREE_MAGIC
) {
3090 dbprintf("bad free block magic # %#x for dir ino %lld "
3092 INT_GET(free
->hdr
.magic
, ARCH_CONVERT
), id
->ino
, dabno
);
3096 maxent
= XFS_DIR2_MAX_FREE_BESTS(mp
);
3097 if (INT_GET(free
->hdr
.firstdb
, ARCH_CONVERT
) !=
3098 XFS_DIR2_DA_TO_DB(mp
, dabno
- mp
->m_dirfreeblk
) * maxent
) {
3100 dbprintf("bad free block firstdb %d for dir ino %lld "
3102 INT_GET(free
->hdr
.firstdb
, ARCH_CONVERT
), id
->ino
, dabno
);
3106 if (INT_GET(free
->hdr
.nvalid
, ARCH_CONVERT
) > maxent
|| INT_GET(free
->hdr
.nvalid
, ARCH_CONVERT
) < 0 ||
3107 INT_GET(free
->hdr
.nused
, ARCH_CONVERT
) > maxent
|| INT_GET(free
->hdr
.nused
, ARCH_CONVERT
) < 0 ||
3108 INT_GET(free
->hdr
.nused
, ARCH_CONVERT
) > INT_GET(free
->hdr
.nvalid
, ARCH_CONVERT
)) {
3110 dbprintf("bad free block nvalid/nused %d/%d for dir "
3111 "ino %lld block %d\n",
3112 INT_GET(free
->hdr
.nvalid
, ARCH_CONVERT
), INT_GET(free
->hdr
.nused
, ARCH_CONVERT
), id
->ino
,
3117 for (used
= i
= 0; i
< INT_GET(free
->hdr
.nvalid
, ARCH_CONVERT
); i
++) {
3118 if (freetab
->nents
<= INT_GET(free
->hdr
.firstdb
, ARCH_CONVERT
) + i
)
3121 ent
= freetab
->ents
[INT_GET(free
->hdr
.firstdb
, ARCH_CONVERT
) + i
];
3122 if (ent
!= INT_GET(free
->bests
[i
], ARCH_CONVERT
)) {
3124 dbprintf("bad free block ent %d is %d should "
3125 "be %d for dir ino %lld block %d\n",
3126 i
, INT_GET(free
->bests
[i
], ARCH_CONVERT
), ent
, id
->ino
, dabno
);
3129 if (INT_GET(free
->bests
[i
], ARCH_CONVERT
) != NULLDATAOFF
)
3131 if (ent
!= NULLDATAOFF
)
3132 freetab
->ents
[INT_GET(free
->hdr
.firstdb
, ARCH_CONVERT
) + i
] = NULLDATAOFF
;
3134 if (used
!= INT_GET(free
->hdr
.nused
, ARCH_CONVERT
)) {
3136 dbprintf("bad free block nused %d should be %d for dir "
3137 "ino %lld block %d\n",
3138 INT_GET(free
->hdr
.nused
, ARCH_CONVERT
), used
, id
->ino
, dabno
);
3144 process_leaf_node_dir_v2_int(
3151 xfs_dir2_data_off_t
*lbp
;
3152 xfs_dir2_leaf_t
*leaf
;
3153 xfs_dir2_leaf_entry_t
*lep
;
3154 xfs_dir2_leaf_tail_t
*ltp
;
3155 xfs_da_intnode_t
*node
;
3158 leaf
= iocur_top
->data
;
3159 switch (INT_GET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
)) {
3160 case XFS_DIR2_LEAF1_MAGIC
:
3161 if (INT_GET(leaf
->hdr
.info
.forw
, ARCH_CONVERT
) || INT_GET(leaf
->hdr
.info
.back
, ARCH_CONVERT
)) {
3163 dbprintf("bad leaf block forw/back pointers "
3164 "%d/%d for dir ino %lld block %d\n",
3165 INT_GET(leaf
->hdr
.info
.forw
, ARCH_CONVERT
),
3166 INT_GET(leaf
->hdr
.info
.back
, ARCH_CONVERT
), id
->ino
, dabno
);
3169 if (dabno
!= mp
->m_dirleafblk
) {
3171 dbprintf("single leaf block for dir ino %lld "
3172 "block %d should be at block %d\n",
3174 (xfs_dablk_t
)mp
->m_dirleafblk
);
3177 ltp
= XFS_DIR2_LEAF_TAIL_P(mp
, leaf
);
3178 lbp
= XFS_DIR2_LEAF_BESTS_P_ARCH(ltp
, ARCH_CONVERT
);
3179 for (i
= 0; i
< INT_GET(ltp
->bestcount
, ARCH_CONVERT
); i
++) {
3180 if (freetab
->nents
<= i
|| freetab
->ents
[i
] != INT_GET(lbp
[i
], ARCH_CONVERT
)) {
3182 dbprintf("bestfree %d for dir ino %lld "
3183 "block %d doesn't match table "
3185 freetab
->nents
<= i
?
3189 XFS_DIR2_DB_TO_DA(mp
, i
),
3190 INT_GET(lbp
[i
], ARCH_CONVERT
));
3192 if (freetab
->nents
> i
)
3193 freetab
->ents
[i
] = NULLDATAOFF
;
3196 case XFS_DIR2_LEAFN_MAGIC
:
3197 /* if it's at the root location then we can check the
3198 * pointers are null XXX */
3200 case XFS_DA_NODE_MAGIC
:
3201 node
= iocur_top
->data
;
3202 if (INT_GET(node
->hdr
.level
, ARCH_CONVERT
) < 1 ||
3203 INT_GET(node
->hdr
.level
, ARCH_CONVERT
) > XFS_DA_NODE_MAXDEPTH
) {
3205 dbprintf("bad node block level %d for dir ino "
3207 INT_GET(node
->hdr
.level
, ARCH_CONVERT
), id
->ino
, dabno
);
3213 dbprintf("bad directory data magic # %#x for dir ino "
3215 INT_GET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
), id
->ino
, dabno
);
3220 for (i
= stale
= 0; i
< INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
); i
++) {
3221 if (INT_GET(lep
[i
].address
, ARCH_CONVERT
) == XFS_DIR2_NULL_DATAPTR
)
3223 else if (dir_hash_see(INT_GET(lep
[i
].hashval
, ARCH_CONVERT
), INT_GET(lep
[i
].address
, ARCH_CONVERT
))) {
3225 dbprintf("dir %lld block %d extra leaf entry "
3227 id
->ino
, dabno
, INT_GET(lep
[i
].hashval
, ARCH_CONVERT
),
3228 INT_GET(lep
[i
].address
, ARCH_CONVERT
));
3232 if (stale
!= INT_GET(leaf
->hdr
.stale
, ARCH_CONVERT
)) {
3234 dbprintf("dir %lld block %d stale mismatch "
3236 id
->ino
, dabno
, stale
,
3237 INT_GET(leaf
->hdr
.stale
, ARCH_CONVERT
));
3243 process_node_dir_v1(
3252 xfs_da_intnode_t
*node
;
3258 v
= verbose
|| id
->ilist
;
3261 while ((dbno
= blkmap_next_off(blkmap
, dbno
, &t
)) != NULLFILEOFF
) {
3262 bno
= blkmap_get(blkmap
, dbno
);
3263 v2
= bno
!= NULLFSBLOCK
&& CHECK_BLIST(bno
);
3264 if (bno
== NULLFSBLOCK
&& dbno
== 0) {
3266 dbprintf("can't read root block for directory "
3272 dbprintf("dir inode %lld block %u=%llu\n", id
->ino
,
3273 (__uint32_t
)dbno
, (xfs_dfsbno_t
)bno
);
3274 if (bno
== NULLFSBLOCK
)
3277 set_cur(&typtab
[TYP_DIR
], XFS_FSB_TO_DADDR(mp
, bno
), blkbb
,
3279 if ((node
= iocur_top
->data
) == NULL
) {
3280 if (!sflag
|| v
|| v2
)
3281 dbprintf("can't read block %u for directory "
3283 (__uint32_t
)dbno
, id
->ino
);
3288 if (INT_GET(node
->hdr
.info
.magic
, ARCH_CONVERT
) == XFS_DA_NODE_MAGIC
)
3290 if (INT_GET(node
->hdr
.info
.magic
, ARCH_CONVERT
) == XFS_DIR_NODE_MAGIC
)
3296 lino
= process_leaf_dir_v1_int(dot
, dotdot
, id
);
3299 if (!sflag
|| v
|| v2
)
3300 dbprintf("multiple .. entries in dir "
3330 perblock
= (int)(mp
->m_sb
.sb_blocksize
/ sizeof(*dqb
));
3331 s
= isproj
? "project" : "user";
3332 exp_flags
= isproj
? XFS_DQ_PROJ
: XFS_DQ_USER
;
3335 while ((qbno
= blkmap_next_off(blkmap
, qbno
, &t
)) !=
3337 bno
= blkmap_get(blkmap
, qbno
);
3338 dqid
= (xfs_dqid_t
)qbno
* perblock
;
3339 cb
= CHECK_BLIST(bno
);
3340 scicb
= !sflag
|| id
->ilist
|| cb
;
3342 set_cur(&typtab
[TYP_DQBLK
], XFS_FSB_TO_DADDR(mp
, bno
), blkbb
,
3344 if ((dqb
= iocur_top
->data
) == NULL
) {
3347 dbprintf("can't read block %lld for %s quota "
3348 "inode (fsblock %lld)\n",
3349 (xfs_dfiloff_t
)qbno
, s
,
3354 for (i
= 0; i
< perblock
; i
++, dqid
++, dqb
++) {
3355 if (verbose
|| id
->ilist
|| cb
)
3356 dbprintf("%s dqblk %lld entry %d id %d bc "
3357 "%lld ic %lld rc %lld\n",
3358 s
, (xfs_dfiloff_t
)qbno
, i
, dqid
,
3359 INT_GET(dqb
->dd_diskdq
.d_bcount
, ARCH_CONVERT
),
3360 INT_GET(dqb
->dd_diskdq
.d_icount
, ARCH_CONVERT
),
3361 INT_GET(dqb
->dd_diskdq
.d_rtbcount
, ARCH_CONVERT
));
3362 if (INT_GET(dqb
->dd_diskdq
.d_magic
, ARCH_CONVERT
) != XFS_DQUOT_MAGIC
) {
3364 dbprintf("bad magic number %#x for %s "
3365 "dqblk %lld entry %d id %d\n",
3366 INT_GET(dqb
->dd_diskdq
.d_magic
, ARCH_CONVERT
), s
,
3367 (xfs_dfiloff_t
)qbno
, i
, dqid
);
3371 if (INT_GET(dqb
->dd_diskdq
.d_version
, ARCH_CONVERT
) != XFS_DQUOT_VERSION
) {
3373 dbprintf("bad version number %#x for "
3374 "%s dqblk %lld entry %d id "
3376 INT_GET(dqb
->dd_diskdq
.d_version
, ARCH_CONVERT
), s
,
3377 (xfs_dfiloff_t
)qbno
, i
, dqid
);
3381 if (INT_GET(dqb
->dd_diskdq
.d_flags
, ARCH_CONVERT
) != exp_flags
) {
3383 dbprintf("bad flags %#x for %s dqblk "
3384 "%lld entry %d id %d\n",
3385 INT_GET(dqb
->dd_diskdq
.d_flags
, ARCH_CONVERT
), s
,
3386 (xfs_dfiloff_t
)qbno
, i
, dqid
);
3390 if (INT_GET(dqb
->dd_diskdq
.d_id
, ARCH_CONVERT
) != dqid
) {
3392 dbprintf("bad id %d for %s dqblk %lld "
3394 INT_GET(dqb
->dd_diskdq
.d_id
, ARCH_CONVERT
), s
,
3395 (xfs_dfiloff_t
)qbno
, i
, dqid
);
3399 quota_add(isproj
? dqid
: -1, isproj
? -1 : dqid
, 1,
3400 INT_GET(dqb
->dd_diskdq
.d_bcount
, ARCH_CONVERT
),
3401 INT_GET(dqb
->dd_diskdq
.d_icount
, ARCH_CONVERT
),
3402 INT_GET(dqb
->dd_diskdq
.d_rtbcount
, ARCH_CONVERT
));
3412 #define xfs_highbit64 libxfs_highbit64 /* for XFS_RTBLOCKLOG macro */
3415 xfs_fileoff_t bmbno
;
3422 xfs_drfsbno_t rtbno
;
3426 xfs_rtword_t
*words
;
3428 bitsperblock
= mp
->m_sb
.sb_blocksize
* NBBY
;
3429 bit
= extno
= prevbit
= start_bmbno
= start_bit
= 0;
3430 bmbno
= NULLFILEOFF
;
3431 while ((bmbno
= blkmap_next_off(blkmap
, bmbno
, &t
)) !=
3433 bno
= blkmap_get(blkmap
, bmbno
);
3434 if (bno
== NULLFSBLOCK
) {
3436 dbprintf("block %lld for rtbitmap inode is "
3438 (xfs_dfiloff_t
)bmbno
);
3443 set_cur(&typtab
[TYP_RTBITMAP
], XFS_FSB_TO_DADDR(mp
, bno
), blkbb
,
3445 if ((words
= iocur_top
->data
) == NULL
) {
3448 dbprintf("can't read block %lld for rtbitmap "
3450 (xfs_dfiloff_t
)bmbno
);
3455 bit
< bitsperblock
&& extno
< mp
->m_sb
.sb_rextents
;
3457 if (isset(words
, bit
)) {
3458 rtbno
= extno
* mp
->m_sb
.sb_rextsize
;
3459 set_rdbmap(rtbno
, mp
->m_sb
.sb_rextsize
,
3463 start_bmbno
= (int)bmbno
;
3467 } else if (prevbit
== 1) {
3468 len
= ((int)bmbno
- start_bmbno
) *
3469 bitsperblock
+ (bit
- start_bit
);
3470 log
= XFS_RTBLOCKLOG(len
);
3471 offs
= XFS_SUMOFFS(mp
, log
, start_bmbno
);
3477 if (extno
== mp
->m_sb
.sb_rextents
)
3481 len
= ((int)bmbno
- start_bmbno
) * bitsperblock
+
3483 log
= XFS_RTBLOCKLOG(len
);
3484 offs
= XFS_SUMOFFS(mp
, log
, start_bmbno
);
3495 xfs_fileoff_t sumbno
;
3498 sumbno
= NULLFILEOFF
;
3499 while ((sumbno
= blkmap_next_off(blkmap
, sumbno
, &t
)) !=
3501 bno
= blkmap_get(blkmap
, sumbno
);
3502 if (bno
== NULLFSBLOCK
) {
3504 dbprintf("block %lld for rtsummary inode is "
3506 (xfs_dfiloff_t
)sumbno
);
3511 set_cur(&typtab
[TYP_RTSUMMARY
], XFS_FSB_TO_DADDR(mp
, bno
),
3512 blkbb
, DB_RING_IGN
, NULL
);
3513 if ((bytes
= iocur_top
->data
) == NULL
) {
3515 dbprintf("can't read block %lld for rtsummary "
3517 (xfs_dfiloff_t
)sumbno
);
3521 memcpy((char *)sumfile
+ sumbno
* mp
->m_sb
.sb_blocksize
, bytes
,
3522 mp
->m_sb
.sb_blocksize
);
3540 xfs_dir2_sf_entry_t
*sfe
;
3543 sf
= &dip
->di_u
.di_dir2sf
;
3545 v
= verbose
|| id
->ilist
;
3547 dbprintf("dir %lld entry . %lld\n", id
->ino
, id
->ino
);
3549 sfe
= XFS_DIR2_SF_FIRSTENTRY(sf
);
3550 offset
= XFS_DIR2_DATA_FIRST_OFFSET
;
3551 for (i
= INT_GET(sf
->hdr
.count
, ARCH_CONVERT
) - 1, i8
= 0; i
>= 0; i
--) {
3552 if ((__psint_t
)sfe
+ XFS_DIR2_SF_ENTSIZE_BYENTRY(sf
, sfe
) -
3553 (__psint_t
)sf
> dip
->di_core
.di_size
) {
3555 dbprintf("dir %llu bad size in entry at %d\n",
3557 (int)((char *)sfe
- (char *)sf
));
3561 lino
= XFS_DIR2_SF_GET_INUMBER_ARCH(sf
, XFS_DIR2_SF_INUMBERP(sfe
), ARCH_CONVERT
);
3562 if (lino
> XFS_DIR2_MAX_SHORT_INUM
)
3564 cid
= find_inode(lino
, 1);
3567 dbprintf("dir %lld entry %*.*s bad inode "
3569 id
->ino
, sfe
->namelen
, sfe
->namelen
,
3576 addname_inode(cid
, (char *)sfe
->name
, sfe
->namelen
);
3579 dbprintf("dir %lld entry %*.*s offset %d %lld\n",
3580 id
->ino
, sfe
->namelen
, sfe
->namelen
, sfe
->name
,
3581 XFS_DIR2_SF_GET_OFFSET_ARCH(sfe
, ARCH_CONVERT
), lino
);
3582 if (XFS_DIR2_SF_GET_OFFSET_ARCH(sfe
, ARCH_CONVERT
) < offset
) {
3584 dbprintf("dir %lld entry %*.*s bad offset %d\n",
3585 id
->ino
, sfe
->namelen
, sfe
->namelen
,
3586 sfe
->name
, XFS_DIR2_SF_GET_OFFSET_ARCH(sfe
, ARCH_CONVERT
));
3590 XFS_DIR2_SF_GET_OFFSET_ARCH(sfe
, ARCH_CONVERT
) +
3591 XFS_DIR2_DATA_ENTSIZE(sfe
->namelen
);
3592 sfe
= XFS_DIR2_SF_NEXTENTRY(sf
, sfe
);
3594 if (i
< 0 && (__psint_t
)sfe
- (__psint_t
)sf
!= dip
->di_core
.di_size
) {
3596 dbprintf("dir %llu size is %lld, should be %u\n",
3597 id
->ino
, dip
->di_core
.di_size
,
3598 (uint
)((char *)sfe
- (char *)sf
));
3601 if (offset
+ (INT_GET(sf
->hdr
.count
, ARCH_CONVERT
) + 2) * sizeof(xfs_dir2_leaf_entry_t
) +
3602 sizeof(xfs_dir2_block_tail_t
) > mp
->m_dirblksize
) {
3604 dbprintf("dir %llu offsets too high\n", id
->ino
);
3607 lino
= XFS_DIR2_SF_GET_INUMBER_ARCH(sf
, &sf
->hdr
.parent
, ARCH_CONVERT
);
3608 if (lino
> XFS_DIR2_MAX_SHORT_INUM
)
3610 cid
= find_inode(lino
, 1);
3615 dbprintf("dir %lld entry .. bad inode number %lld\n",
3620 dbprintf("dir %lld entry .. %lld\n", id
->ino
, lino
);
3621 if (i8
!= sf
->hdr
.i8count
) {
3623 dbprintf("dir %lld i8count mismatch is %d should be "
3625 id
->ino
, sf
->hdr
.i8count
, i8
);
3629 return cid
? lino
: NULLFSINO
;
3633 process_shortform_dir_v1(
3642 xfs_dir_shortform_t
*sf
;
3643 xfs_dir_sf_entry_t
*sfe
;
3646 sf
= &dip
->di_u
.di_dirsf
;
3648 v
= verbose
|| id
->ilist
;
3650 dbprintf("dir %lld entry . %lld\n", id
->ino
, id
->ino
);
3653 for (i
= INT_GET(sf
->hdr
.count
, ARCH_CONVERT
) - 1; i
>= 0; i
--) {
3654 lino
= DIRINO_GET_ARCH(&sfe
->inumber
, ARCH_CONVERT
);
3655 cid
= find_inode(lino
, 1);
3658 dbprintf("dir %lld entry %*.*s bad inode "
3660 id
->ino
, sfe
->namelen
, sfe
->namelen
,
3667 addname_inode(cid
, (char *)sfe
->name
, sfe
->namelen
);
3670 dbprintf("dir %lld entry %*.*s %lld\n", id
->ino
,
3671 sfe
->namelen
, sfe
->namelen
, sfe
->name
, lino
);
3672 sfe
= XFS_DIR_SF_NEXTENTRY(sfe
);
3674 if ((__psint_t
)sfe
- (__psint_t
)sf
!= dip
->di_core
.di_size
)
3675 dbprintf("dir %llu size is %lld, should be %d\n",
3676 id
->ino
, dip
->di_core
.di_size
,
3677 (int)((char *)sfe
- (char *)sf
));
3678 lino
=DIRINO_GET_ARCH(&sf
->hdr
.parent
, ARCH_CONVERT
);
3679 cid
= find_inode(lino
, 1);
3684 dbprintf("dir %lld entry .. bad inode number %lld\n",
3689 dbprintf("dir %lld entry .. %lld\n", id
->ino
, lino
);
3691 return cid
? lino
: NULLFSINO
;
3703 if (qudo
&& userid
!= -1)
3704 quota_add1(qudata
, userid
, dq
, bc
, ic
, rc
);
3705 if (qpdo
&& projid
!= -1)
3706 quota_add1(qpdata
, projid
, dq
, bc
, ic
, rc
);
3722 qh
= (int)((__uint32_t
)id
% QDATA_HASH_SIZE
);
3726 qi
= dq
? &qe
->dq
: &qe
->count
;
3734 qe
= xmalloc(sizeof(*qe
));
3736 qi
= dq
? &qe
->dq
: &qe
->count
;
3740 qi
= dq
? &qe
->count
: &qe
->dq
;
3741 qi
->bc
= qi
->ic
= qi
->rc
= 0;
3755 for (i
= 0; i
< QDATA_HASH_SIZE
; i
++) {
3759 if (qp
->count
.bc
!= qp
->dq
.bc
||
3760 qp
->count
.ic
!= qp
->dq
.ic
||
3761 qp
->count
.rc
!= qp
->dq
.rc
) {
3763 dbprintf("%s quota id %d, have/exp",
3765 if (qp
->count
.bc
!= qp
->dq
.bc
)
3766 dbprintf(" bc %lld/%lld",
3769 if (qp
->count
.ic
!= qp
->dq
.ic
)
3770 dbprintf(" ic %lld/%lld",
3773 if (qp
->count
.rc
!= qp
->dq
.rc
)
3774 dbprintf(" rc %lld/%lld",
3791 qudo
= mp
->m_sb
.sb_uquotino
!= 0 &&
3792 mp
->m_sb
.sb_uquotino
!= NULLFSINO
&&
3793 (mp
->m_sb
.sb_qflags
& XFS_UQUOTA_CHKD
);
3794 qpdo
= mp
->m_sb
.sb_pquotino
!= 0 &&
3795 mp
->m_sb
.sb_pquotino
!= NULLFSINO
&&
3796 (mp
->m_sb
.sb_qflags
& XFS_PQUOTA_CHKD
);
3798 qudata
= xcalloc(QDATA_HASH_SIZE
, sizeof(qdata_t
*));
3800 qpdata
= xcalloc(QDATA_HASH_SIZE
, sizeof(qdata_t
*));
3805 xfs_agnumber_t agno
)
3813 agffreeblks
= agflongest
= 0;
3814 agicount
= agifreecount
= 0;
3816 set_cur(&typtab
[TYP_SB
], XFS_AG_DADDR(mp
, agno
, XFS_SB_DADDR
), 1,
3819 if (!iocur_top
->data
) {
3820 dbprintf("can't read superblock for ag %u\n", agno
);
3826 libxfs_xlate_sb(iocur_top
->data
, sb
, 1, ARCH_CONVERT
, XFS_SB_ALL_BITS
);
3828 if (sb
->sb_magicnum
!= XFS_SB_MAGIC
) {
3830 dbprintf("bad sb magic # %#x in ag %u\n",
3831 sb
->sb_magicnum
, agno
);
3834 if (!XFS_SB_GOOD_VERSION(sb
)) {
3836 dbprintf("bad sb version # %#x in ag %u\n",
3837 sb
->sb_versionnum
, agno
);
3841 if (agno
== 0 && sb
->sb_inprogress
!= 0) {
3843 dbprintf("mkfs not completed successfully\n");
3846 set_dbmap(agno
, XFS_SB_BLOCK(mp
), 1, DBM_SB
, agno
, XFS_SB_BLOCK(mp
));
3847 if (sb
->sb_logstart
&& XFS_FSB_TO_AGNO(mp
, sb
->sb_logstart
) == agno
)
3848 set_dbmap(agno
, XFS_FSB_TO_AGBNO(mp
, sb
->sb_logstart
),
3849 sb
->sb_logblocks
, DBM_LOG
, agno
, XFS_SB_BLOCK(mp
));
3851 set_cur(&typtab
[TYP_AGF
], XFS_AG_DADDR(mp
, agno
, XFS_AGF_DADDR
), 1,
3853 if ((agf
= iocur_top
->data
) == NULL
) {
3854 dbprintf("can't read agf block for ag %u\n", agno
);
3860 if (INT_GET(agf
->agf_magicnum
, ARCH_CONVERT
) != XFS_AGF_MAGIC
) {
3862 dbprintf("bad agf magic # %#x in ag %u\n",
3863 INT_GET(agf
->agf_magicnum
, ARCH_CONVERT
), agno
);
3866 if (!XFS_AGF_GOOD_VERSION(INT_GET(agf
->agf_versionnum
, ARCH_CONVERT
))) {
3868 dbprintf("bad agf version # %#x in ag %u\n",
3869 INT_GET(agf
->agf_versionnum
, ARCH_CONVERT
), agno
);
3872 if (XFS_SB_BLOCK(mp
) != XFS_AGF_BLOCK(mp
))
3873 set_dbmap(agno
, XFS_AGF_BLOCK(mp
), 1, DBM_AGF
, agno
,
3875 if (sb
->sb_agblocks
> INT_GET(agf
->agf_length
, ARCH_CONVERT
))
3876 set_dbmap(agno
, INT_GET(agf
->agf_length
, ARCH_CONVERT
),
3877 sb
->sb_agblocks
- INT_GET(agf
->agf_length
, ARCH_CONVERT
),
3878 DBM_MISSING
, agno
, XFS_SB_BLOCK(mp
));
3880 set_cur(&typtab
[TYP_AGI
], XFS_AG_DADDR(mp
, agno
, XFS_AGI_DADDR
), 1,
3882 if ((agi
= iocur_top
->data
) == NULL
) {
3883 dbprintf("can't read agi block for ag %u\n", agno
);
3890 if (INT_GET(agi
->agi_magicnum
, ARCH_CONVERT
) != XFS_AGI_MAGIC
) {
3892 dbprintf("bad agi magic # %#x in ag %u\n",
3893 INT_GET(agi
->agi_magicnum
, ARCH_CONVERT
), agno
);
3896 if (!XFS_AGI_GOOD_VERSION(INT_GET(agi
->agi_versionnum
, ARCH_CONVERT
))) {
3898 dbprintf("bad agi version # %#x in ag %u\n",
3899 INT_GET(agi
->agi_versionnum
, ARCH_CONVERT
), agno
);
3902 if (XFS_SB_BLOCK(mp
) != XFS_AGI_BLOCK(mp
) &&
3903 XFS_AGF_BLOCK(mp
) != XFS_AGI_BLOCK(mp
))
3904 set_dbmap(agno
, XFS_AGI_BLOCK(mp
), 1, DBM_AGI
, agno
,
3909 INT_GET(agf
->agf_roots
[XFS_BTNUM_BNO
], ARCH_CONVERT
),
3910 INT_GET(agf
->agf_levels
[XFS_BTNUM_BNO
], ARCH_CONVERT
),
3911 1, scanfunc_bno
, TYP_BNOBT
);
3914 INT_GET(agf
->agf_roots
[XFS_BTNUM_CNT
], ARCH_CONVERT
),
3915 INT_GET(agf
->agf_levels
[XFS_BTNUM_CNT
], ARCH_CONVERT
),
3916 1, scanfunc_cnt
, TYP_CNTBT
);
3918 INT_GET(agi
->agi_root
, ARCH_CONVERT
),
3919 INT_GET(agi
->agi_level
, ARCH_CONVERT
),
3920 1, scanfunc_ino
, TYP_INOBT
);
3921 if (INT_GET(agf
->agf_freeblks
, ARCH_CONVERT
) != agffreeblks
) {
3923 dbprintf("agf_freeblks %u, counted %u in ag %u\n",
3924 INT_GET(agf
->agf_freeblks
, ARCH_CONVERT
),
3928 if (INT_GET(agf
->agf_longest
, ARCH_CONVERT
) != agflongest
) {
3930 dbprintf("agf_longest %u, counted %u in ag %u\n",
3931 INT_GET(agf
->agf_longest
, ARCH_CONVERT
),
3935 if (INT_GET(agi
->agi_count
, ARCH_CONVERT
) != agicount
) {
3937 dbprintf("agi_count %u, counted %u in ag %u\n",
3938 INT_GET(agi
->agi_count
, ARCH_CONVERT
),
3942 if (INT_GET(agi
->agi_freecount
, ARCH_CONVERT
) != agifreecount
) {
3944 dbprintf("agi_freecount %u, counted %u in ag %u\n",
3945 INT_GET(agi
->agi_freecount
, ARCH_CONVERT
),
3946 agifreecount
, agno
);
3949 for (i
= 0; i
< XFS_AGI_UNLINKED_BUCKETS
; i
++) {
3950 if (INT_GET(agi
->agi_unlinked
[i
], ARCH_CONVERT
) != NULLAGINO
) {
3952 xfs_agino_t agino
=INT_GET(agi
->agi_unlinked
[i
], ARCH_CONVERT
);
3953 dbprintf("agi unlinked bucket %d is %u in ag "
3954 "%u (inode=%lld)\n", i
, agino
, agno
,
3955 XFS_AGINO_TO_INO(mp
, agno
, agino
));
3969 xfs_agnumber_t seqno
= INT_GET(agf
->agf_seqno
, ARCH_CONVERT
);
3975 if (XFS_SB_BLOCK(mp
) != XFS_AGFL_BLOCK(mp
) &&
3976 XFS_AGF_BLOCK(mp
) != XFS_AGFL_BLOCK(mp
) &&
3977 XFS_AGI_BLOCK(mp
) != XFS_AGFL_BLOCK(mp
))
3978 set_dbmap(seqno
, XFS_AGFL_BLOCK(mp
), 1, DBM_AGFL
, seqno
,
3980 if (INT_GET(agf
->agf_flcount
, ARCH_CONVERT
) == 0)
3983 set_cur(&typtab
[TYP_AGFL
],
3984 XFS_AG_DADDR(mp
, seqno
, XFS_AGFL_DADDR
), 1, DB_RING_IGN
, NULL
);
3985 if ((agfl
= iocur_top
->data
) == NULL
) {
3986 dbprintf("can't read agfl block for ag %u\n", seqno
);
3990 i
= INT_GET(agf
->agf_flfirst
, ARCH_CONVERT
);
3993 bno
= INT_GET(agfl
->agfl_bno
[i
], ARCH_CONVERT
);
3994 set_dbmap(seqno
, bno
, 1, DBM_FREELIST
, seqno
,
3995 XFS_AGFL_BLOCK(mp
));
3997 if (i
== INT_GET(agf
->agf_fllast
, ARCH_CONVERT
))
3999 if (++i
== XFS_AGFL_SIZE
)
4002 if (count
!= INT_GET(agf
->agf_flcount
, ARCH_CONVERT
)) {
4004 dbprintf("freeblk count %u != flcount %u in ag %u\n",
4005 count
, INT_GET(agf
->agf_flcount
, ARCH_CONVERT
),
4017 scan_lbtree_f_t func
,
4020 xfs_drfsbno_t
*totd
,
4021 xfs_drfsbno_t
*toti
,
4028 set_cur(&typtab
[btype
], XFS_FSB_TO_DADDR(mp
, root
), blkbb
, DB_RING_IGN
,
4030 if (iocur_top
->data
== NULL
) {
4032 dbprintf("can't read btree block %u/%u\n",
4033 XFS_FSB_TO_AGNO(mp
, root
),
4034 XFS_FSB_TO_AGBNO(mp
, root
));
4038 (*func
)(iocur_top
->data
, nlevels
- 1, type
, root
, id
, totd
, toti
, nex
,
4039 blkmapp
, isroot
, btype
);
4049 scan_sbtree_f_t func
,
4052 xfs_agnumber_t seqno
= INT_GET(agf
->agf_seqno
, ARCH_CONVERT
);
4055 set_cur(&typtab
[btype
],
4056 XFS_AGB_TO_DADDR(mp
, seqno
, root
), blkbb
, DB_RING_IGN
, NULL
);
4057 if (iocur_top
->data
== NULL
) {
4059 dbprintf("can't read btree block %u/%u\n", seqno
, root
);
4063 (*func
)(iocur_top
->data
, nlevels
- 1, agf
, root
, isroot
);
4069 xfs_btree_lblock_t
*ablock
,
4074 xfs_drfsbno_t
*totd
,
4075 xfs_drfsbno_t
*toti
,
4081 xfs_agblock_t agbno
;
4082 xfs_agnumber_t agno
;
4083 xfs_bmbt_block_t
*block
= (xfs_bmbt_block_t
*)ablock
;
4086 xfs_bmbt_rec_32_t
*rp
;
4088 agno
= XFS_FSB_TO_AGNO(mp
, bno
);
4089 agbno
= XFS_FSB_TO_AGBNO(mp
, bno
);
4090 if (INT_GET(block
->bb_magic
, ARCH_CONVERT
) != XFS_BMAP_MAGIC
) {
4091 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
4092 dbprintf("bad magic # %#x in inode %lld bmbt block "
4094 INT_GET(block
->bb_magic
, ARCH_CONVERT
), id
->ino
, agno
, agbno
);
4097 if (INT_GET(block
->bb_level
, ARCH_CONVERT
) != level
) {
4098 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
4099 dbprintf("expected level %d got %d in inode %lld bmbt "
4101 level
, INT_GET(block
->bb_level
, ARCH_CONVERT
), id
->ino
, agno
, agbno
);
4104 set_dbmap(agno
, agbno
, 1, type
, agno
, agbno
);
4105 set_inomap(agno
, agbno
, 1, id
);
4108 if (INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) > mp
->m_bmap_dmxr
[0] ||
4109 isroot
== 0 && INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) < mp
->m_bmap_dmnr
[0]) {
4110 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
4111 dbprintf("bad btree nrecs (%u, min=%u, max=%u) "
4112 "in inode %lld bmap block %lld\n",
4113 INT_GET(block
->bb_numrecs
, ARCH_CONVERT
), mp
->m_bmap_dmnr
[0],
4114 mp
->m_bmap_dmxr
[0], id
->ino
,
4119 rp
= (xfs_bmbt_rec_32_t
*)
4120 XFS_BTREE_REC_ADDR(mp
->m_sb
.sb_blocksize
, xfs_bmbt
,
4121 block
, 1, mp
->m_bmap_dmxr
[0]);
4122 *nex
+= INT_GET(block
->bb_numrecs
, ARCH_CONVERT
);
4123 process_bmbt_reclist(rp
, INT_GET(block
->bb_numrecs
, ARCH_CONVERT
), type
, id
, totd
,
4127 if (INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) > mp
->m_bmap_dmxr
[1] ||
4128 isroot
== 0 && INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) < mp
->m_bmap_dmnr
[1]) {
4129 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
4130 dbprintf("bad btree nrecs (%u, min=%u, max=%u) in "
4131 "inode %lld bmap block %lld\n",
4132 INT_GET(block
->bb_numrecs
, ARCH_CONVERT
), mp
->m_bmap_dmnr
[1],
4133 mp
->m_bmap_dmxr
[1], id
->ino
, (xfs_dfsbno_t
)bno
);
4137 pp
= XFS_BTREE_PTR_ADDR(mp
->m_sb
.sb_blocksize
, xfs_bmbt
, block
, 1,
4138 mp
->m_bmap_dmxr
[0]);
4139 for (i
= 0; i
< INT_GET(block
->bb_numrecs
, ARCH_CONVERT
); i
++)
4140 scan_lbtree(INT_GET(pp
[i
], ARCH_CONVERT
), level
, scanfunc_bmap
, type
, id
, totd
, toti
,
4141 nex
, blkmapp
, 0, btype
);
4146 xfs_btree_sblock_t
*ablock
,
4152 xfs_alloc_block_t
*block
= (xfs_alloc_block_t
*)ablock
;
4154 xfs_alloc_ptr_t
*pp
;
4155 xfs_alloc_rec_t
*rp
;
4156 xfs_agnumber_t seqno
= INT_GET(agf
->agf_seqno
, ARCH_CONVERT
);
4158 if (INT_GET(block
->bb_magic
, ARCH_CONVERT
) != XFS_ABTB_MAGIC
) {
4159 dbprintf("bad magic # %#x in btbno block %u/%u\n",
4160 INT_GET(block
->bb_magic
, ARCH_CONVERT
), seqno
, bno
);
4165 if (INT_GET(block
->bb_level
, ARCH_CONVERT
) != level
) {
4167 dbprintf("expected level %d got %d in btbno block "
4169 level
, INT_GET(block
->bb_level
, ARCH_CONVERT
), seqno
, bno
);
4172 set_dbmap(seqno
, bno
, 1, DBM_BTBNO
, seqno
, bno
);
4174 if (INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) > mp
->m_alloc_mxr
[0] ||
4175 isroot
== 0 && INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) < mp
->m_alloc_mnr
[0]) {
4176 dbprintf("bad btree nrecs (%u, min=%u, max=%u) in "
4177 "btbno block %u/%u\n",
4178 INT_GET(block
->bb_numrecs
, ARCH_CONVERT
), mp
->m_alloc_mnr
[0],
4179 mp
->m_alloc_mxr
[0], seqno
, bno
);
4183 rp
= XFS_BTREE_REC_ADDR(mp
->m_sb
.sb_blocksize
, xfs_alloc
, block
,
4184 1, mp
->m_alloc_mxr
[0]);
4185 for (i
= 0; i
< INT_GET(block
->bb_numrecs
, ARCH_CONVERT
); i
++) {
4186 set_dbmap(seqno
, INT_GET(rp
[i
].ar_startblock
, ARCH_CONVERT
),
4187 INT_GET(rp
[i
].ar_blockcount
, ARCH_CONVERT
), DBM_FREE1
,
4192 if (INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) > mp
->m_alloc_mxr
[1] ||
4193 isroot
== 0 && INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) < mp
->m_alloc_mnr
[1]) {
4194 dbprintf("bad btree nrecs (%u, min=%u, max=%u) in btbno block "
4196 INT_GET(block
->bb_numrecs
, ARCH_CONVERT
), mp
->m_alloc_mnr
[1],
4197 mp
->m_alloc_mxr
[1], seqno
, bno
);
4201 pp
= XFS_BTREE_PTR_ADDR(mp
->m_sb
.sb_blocksize
, xfs_alloc
, block
, 1,
4202 mp
->m_alloc_mxr
[1]);
4203 for (i
= 0; i
< INT_GET(block
->bb_numrecs
, ARCH_CONVERT
); i
++)
4204 scan_sbtree(agf
, INT_GET(pp
[i
], ARCH_CONVERT
), level
, 0, scanfunc_bno
, TYP_BNOBT
);
4209 xfs_btree_sblock_t
*ablock
,
4215 xfs_alloc_block_t
*block
= (xfs_alloc_block_t
*)ablock
;
4216 xfs_agnumber_t seqno
= INT_GET(agf
->agf_seqno
, ARCH_CONVERT
);
4218 xfs_alloc_ptr_t
*pp
;
4219 xfs_alloc_rec_t
*rp
;
4221 if (INT_GET(block
->bb_magic
, ARCH_CONVERT
) != XFS_ABTC_MAGIC
) {
4222 dbprintf("bad magic # %#x in btcnt block %u/%u\n",
4223 INT_GET(block
->bb_magic
, ARCH_CONVERT
), seqno
, bno
);
4228 if (INT_GET(block
->bb_level
, ARCH_CONVERT
) != level
) {
4230 dbprintf("expected level %d got %d in btcnt block "
4232 level
, INT_GET(block
->bb_level
, ARCH_CONVERT
), seqno
, bno
);
4235 set_dbmap(seqno
, bno
, 1, DBM_BTCNT
, seqno
, bno
);
4237 if (INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) > mp
->m_alloc_mxr
[0] ||
4238 isroot
== 0 && INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) < mp
->m_alloc_mnr
[0]) {
4239 dbprintf("bad btree nrecs (%u, min=%u, max=%u) in "
4240 "btbno block %u/%u\n",
4241 INT_GET(block
->bb_numrecs
, ARCH_CONVERT
), mp
->m_alloc_mnr
[0],
4242 mp
->m_alloc_mxr
[0], seqno
, bno
);
4246 rp
= XFS_BTREE_REC_ADDR(mp
->m_sb
.sb_blocksize
, xfs_alloc
, block
,
4247 1, mp
->m_alloc_mxr
[0]);
4248 for (i
= 0; i
< INT_GET(block
->bb_numrecs
, ARCH_CONVERT
); i
++) {
4249 check_set_dbmap(seqno
, INT_GET(rp
[i
].ar_startblock
, ARCH_CONVERT
),
4250 INT_GET(rp
[i
].ar_blockcount
, ARCH_CONVERT
), DBM_FREE1
, DBM_FREE2
,
4252 fdblocks
+= INT_GET(rp
[i
].ar_blockcount
, ARCH_CONVERT
);
4253 agffreeblks
+= INT_GET(rp
[i
].ar_blockcount
, ARCH_CONVERT
);
4254 if (INT_GET(rp
[i
].ar_blockcount
, ARCH_CONVERT
) > agflongest
)
4255 agflongest
= INT_GET(rp
[i
].ar_blockcount
, ARCH_CONVERT
);
4259 if (INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) > mp
->m_alloc_mxr
[1] ||
4260 isroot
== 0 && INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) < mp
->m_alloc_mnr
[1]) {
4261 dbprintf("bad btree nrecs (%u, min=%u, max=%u) in btbno block "
4263 INT_GET(block
->bb_numrecs
, ARCH_CONVERT
), mp
->m_alloc_mnr
[1],
4264 mp
->m_alloc_mxr
[1], seqno
, bno
);
4268 pp
= XFS_BTREE_PTR_ADDR(mp
->m_sb
.sb_blocksize
, xfs_alloc
, block
, 1,
4269 mp
->m_alloc_mxr
[1]);
4270 for (i
= 0; i
< INT_GET(block
->bb_numrecs
, ARCH_CONVERT
); i
++)
4271 scan_sbtree(agf
, INT_GET(pp
[i
], ARCH_CONVERT
), level
, 0, scanfunc_cnt
, TYP_CNTBT
);
4276 xfs_btree_sblock_t
*ablock
,
4283 xfs_inobt_block_t
*block
= (xfs_inobt_block_t
*)ablock
;
4284 xfs_agnumber_t seqno
= INT_GET(agf
->agf_seqno
, ARCH_CONVERT
);
4290 xfs_inobt_ptr_t
*pp
;
4291 xfs_inobt_rec_t
*rp
;
4293 if (INT_GET(block
->bb_magic
, ARCH_CONVERT
) != XFS_IBT_MAGIC
) {
4294 dbprintf("bad magic # %#x in inobt block %u/%u\n",
4295 INT_GET(block
->bb_magic
, ARCH_CONVERT
), seqno
, bno
);
4299 if (INT_GET(block
->bb_level
, ARCH_CONVERT
) != level
) {
4301 dbprintf("expected level %d got %d in inobt block "
4303 level
, INT_GET(block
->bb_level
, ARCH_CONVERT
), seqno
, bno
);
4306 set_dbmap(seqno
, bno
, 1, DBM_BTINO
, seqno
, bno
);
4308 if (INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) > mp
->m_inobt_mxr
[0] ||
4309 isroot
== 0 && INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) < mp
->m_inobt_mnr
[0]) {
4310 dbprintf("bad btree nrecs (%u, min=%u, max=%u) in "
4311 "inobt block %u/%u\n",
4312 INT_GET(block
->bb_numrecs
, ARCH_CONVERT
), mp
->m_inobt_mnr
[0],
4313 mp
->m_inobt_mxr
[0], seqno
, bno
);
4317 rp
= XFS_BTREE_REC_ADDR(mp
->m_sb
.sb_blocksize
, xfs_inobt
, block
,
4318 1, mp
->m_inobt_mxr
[0]);
4319 for (i
= 0; i
< INT_GET(block
->bb_numrecs
, ARCH_CONVERT
); i
++) {
4320 agino
= INT_GET(rp
[i
].ir_startino
, ARCH_CONVERT
);
4321 off
= XFS_INO_TO_OFFSET(mp
, agino
);
4323 if ((sbversion
& XFS_SB_VERSION_ALIGNBIT
) &&
4324 mp
->m_sb
.sb_inoalignmt
&&
4325 (XFS_INO_TO_AGBNO(mp
, agino
) %
4326 mp
->m_sb
.sb_inoalignmt
))
4327 sbversion
&= ~XFS_SB_VERSION_ALIGNBIT
;
4328 set_dbmap(seqno
, XFS_AGINO_TO_AGBNO(mp
, agino
),
4329 (xfs_extlen_t
)MAX(1,
4330 XFS_INODES_PER_CHUNK
>>
4331 mp
->m_sb
.sb_inopblog
),
4332 DBM_INODE
, seqno
, bno
);
4334 icount
+= XFS_INODES_PER_CHUNK
;
4335 agicount
+= XFS_INODES_PER_CHUNK
;
4336 ifree
+= INT_GET(rp
[i
].ir_freecount
, ARCH_CONVERT
);
4337 agifreecount
+= INT_GET(rp
[i
].ir_freecount
, ARCH_CONVERT
);
4339 set_cur(&typtab
[TYP_INODE
],
4340 XFS_AGB_TO_DADDR(mp
, seqno
,
4341 XFS_AGINO_TO_AGBNO(mp
, agino
)),
4342 (int)XFS_FSB_TO_BB(mp
, XFS_IALLOC_BLOCKS(mp
)),
4344 if (iocur_top
->data
== NULL
) {
4346 dbprintf("can't read inode block "
4349 XFS_AGINO_TO_AGBNO(mp
, agino
));
4353 for (j
= 0, nfree
= 0; j
< XFS_INODES_PER_CHUNK
; j
++) {
4354 if (isfree
= XFS_INOBT_IS_FREE(&rp
[i
], j
, ARCH_CONVERT
))
4356 process_inode(agf
, agino
+ j
,
4357 (xfs_dinode_t
*)((char *)iocur_top
->data
+ ((off
+ j
) << mp
->m_sb
.sb_inodelog
)),
4360 if (nfree
!= INT_GET(rp
[i
].ir_freecount
, ARCH_CONVERT
)) {
4362 dbprintf("ir_freecount/free mismatch, "
4363 "inode chunk %u/%u, freecount "
4366 INT_GET(rp
[i
].ir_freecount
, ARCH_CONVERT
), nfree
);
4373 if (INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) > mp
->m_inobt_mxr
[1] ||
4374 isroot
== 0 && INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) < mp
->m_inobt_mnr
[1]) {
4375 dbprintf("bad btree nrecs (%u, min=%u, max=%u) in inobt block "
4377 INT_GET(block
->bb_numrecs
, ARCH_CONVERT
), mp
->m_inobt_mnr
[1],
4378 mp
->m_inobt_mxr
[1], seqno
, bno
);
4382 pp
= XFS_BTREE_PTR_ADDR(mp
->m_sb
.sb_blocksize
, xfs_inobt
, block
, 1,
4383 mp
->m_inobt_mxr
[1]);
4384 for (i
= 0; i
< INT_GET(block
->bb_numrecs
, ARCH_CONVERT
); i
++)
4385 scan_sbtree(agf
, INT_GET(pp
[i
], ARCH_CONVERT
), level
, 0, scanfunc_ino
, TYP_INOBT
);
4390 xfs_agnumber_t agno
,
4391 xfs_agblock_t agbno
,
4394 xfs_agnumber_t c_agno
,
4395 xfs_agblock_t c_agbno
)
4397 check_set_dbmap(agno
, agbno
, len
, DBM_UNKNOWN
, type
, c_agno
, c_agbno
);
4402 xfs_agnumber_t agno
,
4403 xfs_agblock_t agbno
,
4411 if (!check_inomap(agno
, agbno
, len
, id
->ino
))
4413 mayprint
= verbose
| id
->ilist
| blist_size
;
4414 for (i
= 0, idp
= &inomap
[agno
][agbno
]; i
< len
; i
++, idp
++) {
4417 (verbose
|| id
->ilist
|| CHECK_BLISTA(agno
, agbno
+ i
)))
4418 dbprintf("setting inode to %lld for block %u/%u\n",
4419 id
->ino
, agno
, agbno
+ i
);
4429 check_set_rdbmap(bno
, len
, DBM_UNKNOWN
, type
);
4442 if (!check_rinomap(bno
, len
, id
->ino
))
4444 mayprint
= verbose
| id
->ilist
| blist_size
;
4445 for (i
= 0, idp
= &inomap
[mp
->m_sb
.sb_agcount
][bno
];
4449 if (mayprint
&& (verbose
|| id
->ilist
|| CHECK_BLIST(bno
+ i
)))
4450 dbprintf("setting inode to %lld for rtblock %llu\n",
4462 id
->link_set
= nlink
;
4464 id
->security
= security
;
4465 if (verbose
|| id
->ilist
)
4466 dbprintf("inode %lld nlink %u %s dir\n", id
->ino
, nlink
,
4467 isdir
? "is" : "not");