2 * Copyright (c) 2000-2002,2005 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/
33 #include <xfs/libxfs.h>
50 IS_USER_QUOTA
, IS_PROJECT_QUOTA
, IS_GROUP_QUOTA
,
54 DBM_UNKNOWN
, DBM_AGF
, DBM_AGFL
, DBM_AGI
,
55 DBM_ATTR
, DBM_BTBMAPA
, DBM_BTBMAPD
, DBM_BTBNO
,
56 DBM_BTCNT
, DBM_BTINO
, DBM_DATA
, DBM_DIR
,
57 DBM_FREE1
, DBM_FREE2
, DBM_FREELIST
, DBM_INODE
,
58 DBM_LOG
, DBM_MISSING
, DBM_QUOTA
, DBM_RTBITMAP
,
59 DBM_RTDATA
, DBM_RTFREE
, DBM_RTSUM
, DBM_SB
,
64 typedef struct inodata
{
72 struct inodata
*parent
;
75 #define MIN_INODATA_HASH_SIZE 256
76 #define MAX_INODATA_HASH_SIZE 65536
77 #define INODATA_AVG_HASH_LENGTH 8
79 typedef struct qinfo
{
85 #define QDATA_HASH_SIZE 256
86 typedef struct qdata
{
93 typedef struct blkent
{
94 xfs_fileoff_t startoff
;
96 xfs_fsblock_t blks
[1];
98 #define BLKENT_SIZE(n) \
99 (offsetof(blkent_t, blks) + (sizeof(xfs_fsblock_t) * (n)))
101 typedef struct blkmap
{
106 #define BLKMAP_SIZE(n) \
107 (offsetof(blkmap_t, ents) + (sizeof(blkent_t *) * (n)))
109 typedef struct freetab
{
112 xfs_dir2_data_off_t ents
[1];
114 #define FREETAB_SIZE(n) \
115 (offsetof(freetab_t, ents) + (sizeof(xfs_dir2_data_off_t) * (n)))
117 typedef struct dirhash
{
118 struct dirhash
*next
;
119 xfs_dir2_leaf_entry_t entry
;
122 #define DIR_HASH_SIZE 1024
123 #define DIR_HASH_FUNC(h,a) (((h) ^ (a)) % DIR_HASH_SIZE)
125 static xfs_extlen_t agffreeblks
;
126 static xfs_extlen_t agflongest
;
127 static xfs_agino_t agicount
;
128 static xfs_agino_t agifreecount
;
129 static xfs_fsblock_t
*blist
;
130 static int blist_size
;
131 static char **dbmap
; /* really dbm_t:8 */
132 static dirhash_t
**dirhash
;
134 static __uint64_t fdblocks
;
135 static __uint64_t frextents
;
136 static __uint64_t icount
;
137 static __uint64_t ifree
;
138 static inodata_t
***inodata
;
139 static int inodata_hash_size
;
140 static inodata_t
***inomap
;
144 static qdata_t
**qpdata
;
146 static qdata_t
**qudata
;
148 static qdata_t
**qgdata
;
150 static unsigned sbversion
;
151 static int sbver_err
;
152 static int serious_error
;
154 static xfs_suminfo_t
*sumcompute
;
155 static xfs_suminfo_t
*sumfile
;
156 static const char *typename
[] = {
186 #define CHECK_BLIST(b) (blist_size && check_blist(b))
187 #define CHECK_BLISTA(a,b) \
188 (blist_size && check_blist(XFS_AGB_TO_FSB(mp, a, b)))
190 typedef void (*scan_lbtree_f_t
)(xfs_btree_lblock_t
*block
,
202 typedef void (*scan_sbtree_f_t
)(xfs_btree_sblock_t
*block
,
208 static void add_blist(xfs_fsblock_t bno
);
209 static void add_ilist(xfs_ino_t ino
);
210 static void addlink_inode(inodata_t
*id
);
211 static void addname_inode(inodata_t
*id
, char *name
, int namelen
);
212 static void addparent_inode(inodata_t
*id
, xfs_ino_t parent
);
213 static void blkent_append(blkent_t
**entp
, xfs_fsblock_t b
,
215 static blkent_t
*blkent_new(xfs_fileoff_t o
, xfs_fsblock_t b
,
217 static void blkent_prepend(blkent_t
**entp
, xfs_fsblock_t b
,
219 static blkmap_t
*blkmap_alloc(xfs_extnum_t
);
220 static void blkmap_free(blkmap_t
*blkmap
);
221 static xfs_fsblock_t
blkmap_get(blkmap_t
*blkmap
, xfs_fileoff_t o
);
222 static int blkmap_getn(blkmap_t
*blkmap
, xfs_fileoff_t o
, int nb
,
224 static void blkmap_grow(blkmap_t
**blkmapp
, blkent_t
**entp
,
226 static xfs_fileoff_t
blkmap_next_off(blkmap_t
*blkmap
, xfs_fileoff_t o
,
228 static void blkmap_set_blk(blkmap_t
**blkmapp
, xfs_fileoff_t o
,
230 static void blkmap_set_ext(blkmap_t
**blkmapp
, xfs_fileoff_t o
,
231 xfs_fsblock_t b
, xfs_extlen_t c
);
232 static void blkmap_shrink(blkmap_t
*blkmap
, blkent_t
**entp
);
233 static int blockfree_f(int argc
, char **argv
);
234 static int blockget_f(int argc
, char **argv
);
235 static int blocktrash_f(int argc
, char **argv
);
236 static int blockuse_f(int argc
, char **argv
);
237 static int check_blist(xfs_fsblock_t bno
);
238 static void check_dbmap(xfs_agnumber_t agno
, xfs_agblock_t agbno
,
239 xfs_extlen_t len
, dbm_t type
);
240 static int check_inomap(xfs_agnumber_t agno
, xfs_agblock_t agbno
,
241 xfs_extlen_t len
, xfs_ino_t c_ino
);
242 static void check_linkcounts(xfs_agnumber_t agno
);
243 static int check_range(xfs_agnumber_t agno
, xfs_agblock_t agbno
,
245 static void check_rdbmap(xfs_drfsbno_t bno
, xfs_extlen_t len
,
247 static int check_rinomap(xfs_drfsbno_t bno
, xfs_extlen_t len
,
249 static void check_rootdir(void);
250 static int check_rrange(xfs_drfsbno_t bno
, xfs_extlen_t len
);
251 static void check_set_dbmap(xfs_agnumber_t agno
,
252 xfs_agblock_t agbno
, xfs_extlen_t len
,
253 dbm_t type1
, dbm_t type2
,
254 xfs_agnumber_t c_agno
,
255 xfs_agblock_t c_agbno
);
256 static void check_set_rdbmap(xfs_drfsbno_t bno
, xfs_extlen_t len
,
257 dbm_t type1
, dbm_t type2
);
258 static void check_summary(void);
259 static void checknot_dbmap(xfs_agnumber_t agno
, xfs_agblock_t agbno
,
260 xfs_extlen_t len
, int typemask
);
261 static void checknot_rdbmap(xfs_drfsbno_t bno
, xfs_extlen_t len
,
263 static void dir_hash_add(xfs_dahash_t hash
,
264 xfs_dir2_dataptr_t addr
);
265 static void dir_hash_check(inodata_t
*id
, int v
);
266 static void dir_hash_done(void);
267 static void dir_hash_init(void);
268 static int dir_hash_see(xfs_dahash_t hash
,
269 xfs_dir2_dataptr_t addr
);
270 static inodata_t
*find_inode(xfs_ino_t ino
, int add
);
271 static void free_inodata(xfs_agnumber_t agno
);
272 static int init(int argc
, char **argv
);
273 static char *inode_name(xfs_ino_t ino
, inodata_t
**ipp
);
274 static int ncheck_f(int argc
, char **argv
);
275 static char *prepend_path(char *oldpath
, char *parent
);
276 static xfs_ino_t
process_block_dir_v2(blkmap_t
*blkmap
, int *dot
,
277 int *dotdot
, inodata_t
*id
);
278 static void process_bmbt_reclist(xfs_bmbt_rec_32_t
*rp
, int numrecs
,
279 dbm_t type
, inodata_t
*id
,
282 static void process_btinode(inodata_t
*id
, xfs_dinode_t
*dip
,
283 dbm_t type
, xfs_drfsbno_t
*totd
,
284 xfs_drfsbno_t
*toti
, xfs_extnum_t
*nex
,
285 blkmap_t
**blkmapp
, int whichfork
);
286 static xfs_ino_t
process_data_dir_v2(int *dot
, int *dotdot
,
287 inodata_t
*id
, int v
,
289 freetab_t
**freetabp
);
290 static xfs_dir2_data_free_t
291 *process_data_dir_v2_freefind(xfs_dir2_data_t
*data
,
292 xfs_dir2_data_unused_t
*dup
);
293 static void process_dir(xfs_dinode_t
*dip
, blkmap_t
*blkmap
,
295 static int process_dir_v1(xfs_dinode_t
*dip
, blkmap_t
*blkmap
,
296 int *dot
, int *dotdot
, inodata_t
*id
,
298 static int process_dir_v2(xfs_dinode_t
*dip
, blkmap_t
*blkmap
,
299 int *dot
, int *dotdot
, inodata_t
*id
,
301 static void process_exinode(inodata_t
*id
, xfs_dinode_t
*dip
,
302 dbm_t type
, xfs_drfsbno_t
*totd
,
303 xfs_drfsbno_t
*toti
, xfs_extnum_t
*nex
,
304 blkmap_t
**blkmapp
, int whichfork
);
305 static void process_inode(xfs_agf_t
*agf
, xfs_agino_t agino
,
306 xfs_dinode_t
*dip
, int isfree
);
307 static void process_lclinode(inodata_t
*id
, xfs_dinode_t
*dip
,
308 dbm_t type
, xfs_drfsbno_t
*totd
,
309 xfs_drfsbno_t
*toti
, xfs_extnum_t
*nex
,
310 blkmap_t
**blkmapp
, int whichfork
);
311 static xfs_ino_t
process_leaf_dir_v1(blkmap_t
*blkmap
, int *dot
,
312 int *dotdot
, inodata_t
*id
);
313 static xfs_ino_t
process_leaf_dir_v1_int(int *dot
, int *dotdot
,
315 static xfs_ino_t
process_leaf_node_dir_v2(blkmap_t
*blkmap
, int *dot
,
316 int *dotdot
, inodata_t
*id
,
317 xfs_fsize_t dirsize
);
318 static void process_leaf_node_dir_v2_free(inodata_t
*id
, int v
,
321 static void process_leaf_node_dir_v2_int(inodata_t
*id
, int v
,
324 static xfs_ino_t
process_node_dir_v1(blkmap_t
*blkmap
, int *dot
,
325 int *dotdot
, inodata_t
*id
);
326 static void process_quota(qtype_t qtype
, inodata_t
*id
,
328 static void process_rtbitmap(blkmap_t
*blkmap
);
329 static void process_rtsummary(blkmap_t
*blkmap
);
330 static xfs_ino_t
process_sf_dir_v2(xfs_dinode_t
*dip
, int *dot
,
331 int *dotdot
, inodata_t
*id
);
332 static xfs_ino_t
process_shortform_dir_v1(xfs_dinode_t
*dip
, int *dot
,
333 int *dotdot
, inodata_t
*id
);
334 static void quota_add(xfs_dqid_t
*p
, xfs_dqid_t
*g
, xfs_dqid_t
*u
,
335 int dq
, xfs_qcnt_t bc
, xfs_qcnt_t ic
,
337 static void quota_add1(qdata_t
**qt
, xfs_dqid_t id
, int dq
,
338 xfs_qcnt_t bc
, xfs_qcnt_t ic
,
340 static void quota_check(char *s
, qdata_t
**qt
);
341 static void quota_init(void);
342 static void scan_ag(xfs_agnumber_t agno
);
343 static void scan_freelist(xfs_agf_t
*agf
);
344 static void scan_lbtree(xfs_fsblock_t root
, int nlevels
,
345 scan_lbtree_f_t func
, dbm_t type
,
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 scan_sbtree(xfs_agf_t
*agf
, xfs_agblock_t root
,
351 int nlevels
, int isroot
,
352 scan_sbtree_f_t func
, typnm_t btype
);
353 static void scanfunc_bmap(xfs_btree_lblock_t
*ablock
, int level
,
354 dbm_t type
, xfs_fsblock_t bno
,
355 inodata_t
*id
, xfs_drfsbno_t
*totd
,
356 xfs_drfsbno_t
*toti
, xfs_extnum_t
*nex
,
357 blkmap_t
**blkmapp
, int isroot
,
359 static void scanfunc_bno(xfs_btree_sblock_t
*ablock
, int level
,
360 xfs_agf_t
*agf
, xfs_agblock_t bno
,
362 static void scanfunc_cnt(xfs_btree_sblock_t
*ablock
, int level
,
363 xfs_agf_t
*agf
, xfs_agblock_t bno
,
365 static void scanfunc_ino(xfs_btree_sblock_t
*ablock
, int level
,
366 xfs_agf_t
*agf
, xfs_agblock_t bno
,
368 static void set_dbmap(xfs_agnumber_t agno
, xfs_agblock_t agbno
,
369 xfs_extlen_t len
, dbm_t type
,
370 xfs_agnumber_t c_agno
, xfs_agblock_t c_agbno
);
371 static void set_inomap(xfs_agnumber_t agno
, xfs_agblock_t agbno
,
372 xfs_extlen_t len
, inodata_t
*id
);
373 static void set_rdbmap(xfs_drfsbno_t bno
, xfs_extlen_t len
,
375 static void set_rinomap(xfs_drfsbno_t bno
, xfs_extlen_t len
,
377 static void setlink_inode(inodata_t
*id
, nlink_t nlink
, int isdir
,
380 static const cmdinfo_t blockfree_cmd
=
381 { "blockfree", NULL
, blockfree_f
, 0, 0, 0,
382 NULL
, "free block usage information", NULL
};
383 static const cmdinfo_t blockget_cmd
=
384 { "blockget", "check", blockget_f
, 0, -1, 0,
385 "[-s|-v] [-n] [-t] [-b bno]... [-i ino] ...",
386 "get block usage and check consistency", NULL
};
387 static const cmdinfo_t blocktrash_cmd
=
388 { "blocktrash", NULL
, blocktrash_f
, 0, -1, 0,
389 "[-n count] [-x minlen] [-y maxlen] [-s seed] [-0123] [-t type] ...",
390 "trash randomly selected block(s)", NULL
};
391 static const cmdinfo_t blockuse_cmd
=
392 { "blockuse", NULL
, blockuse_f
, 0, 3, 0,
393 "[-n] [-c blockcount]",
394 "print usage for current block(s)", NULL
};
395 static const cmdinfo_t ncheck_cmd
=
396 { "ncheck", NULL
, ncheck_f
, 0, -1, 0,
398 "print inode-name pairs", NULL
};
406 blist
= xrealloc(blist
, blist_size
* sizeof(bno
));
407 blist
[blist_size
- 1] = bno
;
416 id
= find_inode(ino
, 1);
418 dbprintf("-i %lld bad inode number\n", ino
);
429 if (verbose
|| id
->ilist
)
430 dbprintf("inode %lld add link, now %u\n", id
->ino
,
440 if (!nflag
|| id
->name
)
442 id
->name
= xmalloc(namelen
+ 1);
443 memcpy(id
->name
, name
, namelen
);
444 id
->name
[namelen
] = '\0';
454 pid
= find_inode(parent
, 1);
456 if (verbose
|| id
->ilist
|| (pid
&& pid
->ilist
))
457 dbprintf("inode %lld parent %lld\n", id
->ino
, parent
);
470 *entp
= ent
= xrealloc(ent
, BLKENT_SIZE(c
+ ent
->nblks
));
471 for (i
= 0; i
< c
; i
++)
472 ent
->blks
[ent
->nblks
+ i
] = b
+ i
;
485 ent
= xmalloc(BLKENT_SIZE(c
));
488 for (i
= 0; i
< c
; i
++)
489 ent
->blks
[i
] = b
+ i
;
504 newent
= xmalloc(BLKENT_SIZE(oldent
->nblks
+ c
));
505 newent
->nblks
= oldent
->nblks
+ c
;
506 newent
->startoff
= oldent
->startoff
- c
;
507 for (i
= 0; i
< c
; i
++)
508 newent
->blks
[i
] = b
+ c
;
509 for (; i
< oldent
->nblks
+ c
; i
++)
510 newent
->blks
[i
] = oldent
->blks
[i
- c
];
523 blkmap
= xmalloc(BLKMAP_SIZE(nex
));
524 blkmap
->naents
= nex
;
536 for (i
= 0, entp
= blkmap
->ents
; i
< blkmap
->nents
; i
++, entp
++)
550 for (i
= 0, entp
= blkmap
->ents
; i
< blkmap
->nents
; i
++, entp
++) {
552 if (o
>= ent
->startoff
&& o
< ent
->startoff
+ ent
->nblks
)
553 return ent
->blks
[o
- ent
->startoff
];
572 for (i
= nex
= 0, bmp
= NULL
, entp
= blkmap
->ents
;
576 if (ent
->startoff
>= o
+ nb
)
578 if (ent
->startoff
+ ent
->nblks
<= o
)
580 for (ento
= ent
->startoff
;
581 ento
< ent
->startoff
+ ent
->nblks
&& ento
< o
+ nb
;
586 bmp
[nex
- 1].startoff
+ bmp
[nex
- 1].blockcount
==
588 bmp
[nex
- 1].startblock
+ bmp
[nex
- 1].blockcount
==
589 ent
->blks
[ento
- ent
->startoff
])
590 bmp
[nex
- 1].blockcount
++;
592 bmp
= realloc(bmp
, ++nex
* sizeof(*bmp
));
593 bmp
[nex
- 1].startoff
= ento
;
594 bmp
[nex
- 1].startblock
=
595 ent
->blks
[ento
- ent
->startoff
];
596 bmp
[nex
- 1].blockcount
= 1;
597 bmp
[nex
- 1].flag
= 0;
616 idx
= (int)(entp
- blkmap
->ents
);
617 if (blkmap
->naents
== blkmap
->nents
) {
618 blkmap
= xrealloc(blkmap
, BLKMAP_SIZE(blkmap
->nents
+ 1));
622 for (i
= blkmap
->nents
; i
> idx
; i
--)
623 blkmap
->ents
[i
] = blkmap
->ents
[i
- 1];
624 blkmap
->ents
[idx
] = newent
;
636 ent
= blkmap
->ents
[blkmap
->nents
- 1];
637 return ent
->startoff
+ ent
->nblks
;
651 if (o
== NULLFILEOFF
) {
653 ent
= blkmap
->ents
[0];
654 return ent
->startoff
;
656 entp
= &blkmap
->ents
[*t
];
658 if (o
< ent
->startoff
+ ent
->nblks
- 1)
661 if (entp
>= &blkmap
->ents
[blkmap
->nents
])
665 return ent
->startoff
;
680 for (entp
= blkmap
->ents
; entp
< &blkmap
->ents
[blkmap
->nents
]; entp
++) {
682 if (o
< ent
->startoff
- 1) {
683 ent
= blkent_new(o
, b
, 1);
684 blkmap_grow(blkmapp
, entp
, ent
);
687 if (o
== ent
->startoff
- 1) {
688 blkent_prepend(entp
, b
, 1);
691 if (o
>= ent
->startoff
&& o
< ent
->startoff
+ ent
->nblks
) {
692 ent
->blks
[o
- ent
->startoff
] = b
;
695 if (o
> ent
->startoff
+ ent
->nblks
)
697 blkent_append(entp
, b
, 1);
698 if (entp
== &blkmap
->ents
[blkmap
->nents
- 1])
702 if (ent
->startoff
+ ent
->nblks
< nextent
->startoff
)
704 blkent_append(entp
, nextent
->blks
[0], nextent
->nblks
);
705 blkmap_shrink(blkmap
, &entp
[1]);
708 ent
= blkent_new(o
, b
, 1);
709 blkmap_grow(blkmapp
, entp
, ent
);
725 if (!blkmap
->nents
) {
726 blkmap
->ents
[0] = blkent_new(o
, b
, c
);
730 entp
= &blkmap
->ents
[blkmap
->nents
- 1];
732 if (ent
->startoff
+ ent
->nblks
== o
) {
733 blkent_append(entp
, b
, c
);
736 if (ent
->startoff
+ ent
->nblks
< o
) {
737 ent
= blkent_new(o
, b
, c
);
738 blkmap_grow(blkmapp
, &blkmap
->ents
[blkmap
->nents
], ent
);
741 for (i
= 0; i
< c
; i
++)
742 blkmap_set_blk(blkmapp
, o
+ i
, b
+ i
);
754 idx
= (int)(entp
- blkmap
->ents
);
755 for (i
= idx
+ 1; i
< blkmap
->nents
; i
++)
756 blkmap
->ents
[i
] = blkmap
->ents
[i
- 1];
770 dbprintf("block usage information not allocated\n");
773 rt
= mp
->m_sb
.sb_rextents
!= 0;
774 for (c
= 0; c
< mp
->m_sb
.sb_agcount
; c
++) {
784 sumcompute
= sumfile
= NULL
;
796 * Check consistency of xfs filesystem contents.
808 dbprintf("already have block usage information\n");
811 if (!init(argc
, argv
))
813 oldprefix
= dbprefix
;
815 for (agno
= 0, sbyell
= 0; agno
< mp
->m_sb
.sb_agcount
; agno
++) {
817 if (sbver_err
> 4 && !sbyell
&& sbver_err
>= agno
) {
819 dbprintf("WARNING: this may be a newer XFS "
830 dbprefix
= oldprefix
;
835 * Check that there are no blocks either
836 * a) unaccounted for or
837 * b) bno-free but not cnt-free
839 if (!tflag
) { /* are we in test mode, faking out freespace? */
840 for (agno
= 0; agno
< mp
->m_sb
.sb_agcount
; agno
++)
841 checknot_dbmap(agno
, 0, mp
->m_sb
.sb_agblocks
,
842 (1 << DBM_UNKNOWN
) | (1 << DBM_FREE1
));
844 for (agno
= 0; agno
< mp
->m_sb
.sb_agcount
; agno
++)
845 check_linkcounts(agno
);
846 if (mp
->m_sb
.sb_rblocks
) {
848 (xfs_extlen_t
)(mp
->m_sb
.sb_rextents
*
849 mp
->m_sb
.sb_rextsize
),
853 if (mp
->m_sb
.sb_icount
!= icount
) {
855 dbprintf("sb_icount %lld, counted %lld\n",
856 mp
->m_sb
.sb_icount
, icount
);
859 if (mp
->m_sb
.sb_ifree
!= ifree
) {
861 dbprintf("sb_ifree %lld, counted %lld\n",
862 mp
->m_sb
.sb_ifree
, ifree
);
865 if (mp
->m_sb
.sb_fdblocks
!= fdblocks
) {
867 dbprintf("sb_fdblocks %lld, counted %lld\n",
868 mp
->m_sb
.sb_fdblocks
, fdblocks
);
871 if (mp
->m_sb
.sb_frextents
!= frextents
) {
873 dbprintf("sb_frextents %lld, counted %lld\n",
874 mp
->m_sb
.sb_frextents
, frextents
);
877 if ((sbversion
& XFS_SB_VERSION_ATTRBIT
) &&
878 !XFS_SB_VERSION_HASATTR(&mp
->m_sb
)) {
880 dbprintf("sb versionnum missing attr bit %x\n",
881 XFS_SB_VERSION_ATTRBIT
);
884 if ((sbversion
& XFS_SB_VERSION_NLINKBIT
) &&
885 !XFS_SB_VERSION_HASNLINK(&mp
->m_sb
)) {
887 dbprintf("sb versionnum missing nlink bit %x\n",
888 XFS_SB_VERSION_NLINKBIT
);
891 if ((sbversion
& XFS_SB_VERSION_QUOTABIT
) &&
892 !XFS_SB_VERSION_HASQUOTA(&mp
->m_sb
)) {
894 dbprintf("sb versionnum missing quota bit %x\n",
895 XFS_SB_VERSION_QUOTABIT
);
898 if (!(sbversion
& XFS_SB_VERSION_ALIGNBIT
) &&
899 XFS_SB_VERSION_HASALIGN(&mp
->m_sb
)) {
901 dbprintf("sb versionnum extra align bit %x\n",
902 XFS_SB_VERSION_ALIGNBIT
);
906 quota_check("user", qudata
);
908 quota_check("project", qpdata
);
910 quota_check("group", qgdata
);
911 if (sbver_err
> mp
->m_sb
.sb_agcount
/ 2)
912 dbprintf("WARNING: this may be a newer XFS filesystem.\n");
915 dbprefix
= oldprefix
;
919 typedef struct ltab
{
940 static char *modestr
[] = {
941 "zeroed", "set", "flipped", "randomized"
944 len
= (int)((random() % (ltabp
->max
- ltabp
->min
+ 1)) + ltabp
->min
);
945 offset
= (int)(random() % (int)(mp
->m_sb
.sb_blocksize
* NBBY
));
948 set_cur(&typtab
[DBM_UNKNOWN
],
949 XFS_AGB_TO_DADDR(mp
, agno
, agbno
), blkbb
, DB_RING_IGN
, NULL
);
950 if ((buf
= iocur_top
->data
) == NULL
) {
951 dbprintf("can't read block %u/%u for trashing\n", agno
, agbno
);
955 for (bitno
= 0; bitno
< len
; bitno
++) {
956 bit
= (offset
+ bitno
) % (mp
->m_sb
.sb_blocksize
* NBBY
);
968 newbit
= (buf
[byte
] & mask
) == 0;
971 newbit
= (int)random() & 1;
981 printf("blocktrash: %u/%u %s block %d bit%s starting %d:%d %s\n",
982 agno
, agbno
, typename
[type
], len
, len
== 1 ? "" : "s",
983 offset
/ NBBY
, offset
% NBBY
, modestr
[mode
]);
994 xfs_drfsbno_t blocks
;
1007 xfs_drfsbno_t randb
;
1013 dbprintf("must run blockget first\n");
1021 gettimeofday(&now
, NULL
);
1022 seed
= (unsigned int)(now
.tv_sec
^ now
.tv_usec
);
1025 goodmask
= (1 << DBM_AGF
) |
1029 (1 << DBM_BTBMAPA
) |
1030 (1 << DBM_BTBMAPD
) |
1037 (1 << DBM_RTBITMAP
) |
1040 while ((c
= getopt(argc
, argv
, "0123n:s:t:x:y:")) != EOF
) {
1055 count
= (int)strtol(optarg
, &p
, 0);
1056 if (*p
!= '\0' || count
<= 0) {
1057 dbprintf("bad blocktrash count %s\n", optarg
);
1062 seed
= (uint
)strtoul(optarg
, &p
, 0);
1066 for (i
= 0; typename
[i
]; i
++) {
1067 if (strcmp(typename
[i
], optarg
) == 0)
1070 if (!typename
[i
] || (((1 << i
) & goodmask
) == 0)) {
1071 dbprintf("bad blocktrash type %s\n", optarg
);
1077 min
= (int)strtol(optarg
, &p
, 0);
1078 if (*p
!= '\0' || min
<= 0 ||
1079 min
> mp
->m_sb
.sb_blocksize
* NBBY
) {
1080 dbprintf("bad blocktrash min %s\n", optarg
);
1085 max
= (int)strtol(optarg
, &p
, 0);
1086 if (*p
!= '\0' || max
<= 0 ||
1087 max
> mp
->m_sb
.sb_blocksize
* NBBY
) {
1088 dbprintf("bad blocktrash max %s\n", optarg
);
1093 dbprintf("bad option for blocktrash command\n");
1098 dbprintf("bad min/max for blocktrash command\n");
1103 lentab
= xmalloc(sizeof(ltab_t
));
1104 lentab
->min
= lentab
->max
= min
;
1106 for (i
= min
+ 1; i
<= max
; i
++) {
1107 if ((i
& (i
- 1)) == 0) {
1108 lentab
= xrealloc(lentab
,
1109 sizeof(ltab_t
) * (lentablen
+ 1));
1110 lentab
[lentablen
].min
= lentab
[lentablen
].max
= i
;
1113 lentab
[lentablen
- 1].max
= i
;
1115 for (blocks
= 0, agno
= 0; agno
< mp
->m_sb
.sb_agcount
; agno
++) {
1116 for (agbno
= 0, p
= dbmap
[agno
];
1117 agbno
< mp
->m_sb
.sb_agblocks
;
1119 if ((1 << *p
) & tmask
)
1124 dbprintf("blocktrash: no matching blocks\n");
1128 dbprintf("blocktrash: seed %u\n", seed
);
1130 for (i
= 0; i
< count
; i
++) {
1131 randb
= (xfs_drfsbno_t
)((((__int64_t
)random() << 32) |
1132 random()) % blocks
);
1133 for (bi
= 0, agno
= 0, done
= 0;
1134 !done
&& agno
< mp
->m_sb
.sb_agcount
;
1136 for (agbno
= 0, p
= dbmap
[agno
];
1137 agbno
< mp
->m_sb
.sb_agblocks
;
1139 if (!((1 << *p
) & tmask
))
1143 blocktrash_b(agno
, agbno
, (dbm_t
)*p
,
1144 &lentab
[random() % lentablen
], mode
);
1159 xfs_agblock_t agbno
;
1160 xfs_agnumber_t agno
;
1170 dbprintf("must run blockget first\n");
1176 fsb
= XFS_DADDR_TO_FSB(mp
, iocur_top
->off
>> BBSHIFT
);
1177 agno
= XFS_FSB_TO_AGNO(mp
, fsb
);
1178 end
= agbno
= XFS_FSB_TO_AGBNO(mp
, fsb
);
1179 while ((c
= getopt(argc
, argv
, "c:n")) != EOF
) {
1182 count
= (int)strtol(optarg
, &p
, 0);
1183 end
= agbno
+ count
- 1;
1184 if (*p
!= '\0' || count
<= 0 ||
1185 end
>= mp
->m_sb
.sb_agblocks
) {
1186 dbprintf("bad blockuse count %s\n", optarg
);
1192 dbprintf("must run blockget -n first\n");
1198 dbprintf("bad option for blockuse command\n");
1202 while (agbno
<= end
) {
1203 p
= &dbmap
[agno
][agbno
];
1204 i
= inomap
[agno
][agbno
];
1205 dbprintf("block %llu (%u/%u) type %s",
1206 (xfs_dfsbno_t
)XFS_AGB_TO_FSB(mp
, agno
, agbno
),
1207 agno
, agbno
, typename
[(dbm_t
)*p
]);
1209 dbprintf(" inode %lld", i
->ino
);
1210 if (shownames
&& (p
= inode_name(i
->ino
, NULL
))) {
1227 for (i
= 0; i
< blist_size
; i
++) {
1228 if (blist
[i
] == bno
)
1236 xfs_agnumber_t agno
,
1237 xfs_agblock_t agbno
,
1244 for (i
= 0, p
= &dbmap
[agno
][agbno
]; i
< len
; i
++, p
++) {
1245 if ((dbm_t
)*p
!= type
) {
1246 if (!sflag
|| CHECK_BLISTA(agno
, agbno
+ i
))
1247 dbprintf("block %u/%u expected type %s got "
1249 agno
, agbno
+ i
, typename
[type
],
1250 typename
[(dbm_t
)*p
]);
1259 add_command(&blockfree_cmd
);
1260 add_command(&blockget_cmd
);
1262 add_command(&blocktrash_cmd
);
1263 add_command(&blockuse_cmd
);
1264 add_command(&ncheck_cmd
);
1269 xfs_agnumber_t agno
,
1270 xfs_agblock_t agbno
,
1278 if (!check_range(agno
, agbno
, len
)) {
1279 dbprintf("blocks %u/%u..%u claimed by inode %lld\n",
1280 agno
, agbno
, agbno
+ len
- 1, c_ino
);
1283 for (i
= 0, rval
= 1, idp
= &inomap
[agno
][agbno
]; i
< len
; i
++, idp
++) {
1285 if (!sflag
|| (*idp
)->ilist
||
1286 CHECK_BLISTA(agno
, agbno
+ i
))
1287 dbprintf("block %u/%u claimed by inode %lld, "
1288 "previous inum %lld\n",
1289 agno
, agbno
+ i
, c_ino
, (*idp
)->ino
);
1299 xfs_agnumber_t agno
)
1307 for (idx
= 0; idx
< inodata_hash_size
; ht
++, idx
++) {
1310 if (ep
->link_set
!= ep
->link_add
|| ep
->link_set
== 0) {
1311 path
= inode_name(ep
->ino
, NULL
);
1312 if (!path
&& ep
->link_add
)
1313 path
= xstrdup("?");
1314 if (!sflag
|| ep
->ilist
) {
1316 dbprintf("link count mismatch "
1317 "for inode %lld (name "
1323 else if (ep
->link_set
)
1324 dbprintf("disconnected inode "
1326 ep
->ino
, ep
->link_set
);
1328 dbprintf("allocated inode %lld "
1329 "has 0 link count\n",
1335 } else if (verbose
|| ep
->ilist
) {
1336 path
= inode_name(ep
->ino
, NULL
);
1338 dbprintf("inode %lld name %s\n",
1351 xfs_agnumber_t agno
,
1352 xfs_agblock_t agbno
,
1356 xfs_agblock_t low
= 0;
1357 xfs_agblock_t high
= 0;
1358 int valid_range
= 0;
1361 if (agno
>= mp
->m_sb
.sb_agcount
||
1362 agbno
+ len
- 1 >= mp
->m_sb
.sb_agblocks
) {
1363 for (i
= 0; i
< len
; i
++) {
1364 cur
= !sflag
|| CHECK_BLISTA(agno
, agbno
+ i
) ? 1 : 0;
1365 if (cur
== 1 && prev
== 0) {
1366 low
= high
= agbno
+ i
;
1368 } else if (cur
== 0 && prev
== 0) {
1370 } else if (cur
== 0 && prev
== 1) {
1372 dbprintf("block %u/%u out of range\n",
1375 dbprintf("blocks %u/%u..%u "
1380 } else if (cur
== 1 && prev
== 1) {
1387 dbprintf("block %u/%u out of range\n",
1390 dbprintf("blocks %u/%u..%u "
1410 for (i
= 0, p
= &dbmap
[mp
->m_sb
.sb_agcount
][bno
]; i
< len
; i
++, p
++) {
1411 if ((dbm_t
)*p
!= type
) {
1412 if (!sflag
|| CHECK_BLIST(bno
+ i
))
1413 dbprintf("rtblock %llu expected type %s got "
1415 bno
+ i
, typename
[type
],
1416 typename
[(dbm_t
)*p
]);
1432 if (!check_rrange(bno
, len
)) {
1433 dbprintf("rtblocks %llu..%llu claimed by inode %lld\n",
1434 bno
, bno
+ len
- 1, c_ino
);
1437 for (i
= 0, rval
= 1, idp
= &inomap
[mp
->m_sb
.sb_agcount
][bno
];
1441 if (!sflag
|| (*idp
)->ilist
|| CHECK_BLIST(bno
+ i
))
1442 dbprintf("rtblock %llu claimed by inode %lld, "
1443 "previous inum %lld\n",
1444 bno
+ i
, c_ino
, (*idp
)->ino
);
1457 id
= find_inode(mp
->m_sb
.sb_rootino
, 0);
1460 dbprintf("root inode %lld is missing\n",
1461 mp
->m_sb
.sb_rootino
);
1463 } else if (!id
->isdir
) {
1464 if (!sflag
|| id
->ilist
)
1465 dbprintf("root inode %lld is not a directory\n",
1466 mp
->m_sb
.sb_rootino
);
1478 if (bno
+ len
- 1 >= mp
->m_sb
.sb_rblocks
) {
1479 for (i
= 0; i
< len
; i
++) {
1480 if (!sflag
|| CHECK_BLIST(bno
+ i
))
1481 dbprintf("rtblock %llu out of range\n",
1492 xfs_agnumber_t agno
,
1493 xfs_agblock_t agbno
,
1497 xfs_agnumber_t c_agno
,
1498 xfs_agblock_t c_agbno
)
1504 if (!check_range(agno
, agbno
, len
)) {
1505 dbprintf("blocks %u/%u..%u claimed by block %u/%u\n", agno
,
1506 agbno
, agbno
+ len
- 1, c_agno
, c_agbno
);
1509 check_dbmap(agno
, agbno
, len
, type1
);
1510 mayprint
= verbose
| blist_size
;
1511 for (i
= 0, p
= &dbmap
[agno
][agbno
]; i
< len
; i
++, p
++) {
1513 if (mayprint
&& (verbose
|| CHECK_BLISTA(agno
, agbno
+ i
)))
1514 dbprintf("setting block %u/%u to %s\n", agno
, agbno
+ i
,
1530 if (!check_rrange(bno
, len
))
1532 check_rdbmap(bno
, len
, type1
);
1533 mayprint
= verbose
| blist_size
;
1534 for (i
= 0, p
= &dbmap
[mp
->m_sb
.sb_agcount
][bno
]; i
< len
; i
++, p
++) {
1536 if (mayprint
&& (verbose
|| CHECK_BLIST(bno
+ i
)))
1537 dbprintf("setting rtblock %llu to %s\n",
1538 bno
+ i
, typename
[type2
]);
1552 for (log
= 0; log
< mp
->m_rsumlevels
; log
++) {
1554 bno
< mp
->m_sb
.sb_rbmblocks
;
1555 bno
++, csp
++, fsp
++) {
1558 dbprintf("rt summary mismatch, size %d "
1559 "block %llu, file: %d, "
1561 log
, bno
, *fsp
, *csp
);
1570 xfs_agnumber_t agno
,
1571 xfs_agblock_t agbno
,
1578 if (!check_range(agno
, agbno
, len
))
1580 for (i
= 0, p
= &dbmap
[agno
][agbno
]; i
< len
; i
++, p
++) {
1581 if ((1 << *p
) & typemask
) {
1582 if (!sflag
|| CHECK_BLISTA(agno
, agbno
+ i
))
1583 dbprintf("block %u/%u type %s not expected\n",
1584 agno
, agbno
+ i
, typename
[(dbm_t
)*p
]);
1599 if (!check_rrange(bno
, len
))
1601 for (i
= 0, p
= &dbmap
[mp
->m_sb
.sb_agcount
][bno
]; i
< len
; i
++, p
++) {
1602 if ((1 << *p
) & typemask
) {
1603 if (!sflag
|| CHECK_BLIST(bno
+ i
))
1604 dbprintf("rtblock %llu type %s not expected\n",
1605 bno
+ i
, typename
[(dbm_t
)*p
]);
1614 xfs_dir2_dataptr_t addr
)
1619 i
= DIR_HASH_FUNC(hash
, addr
);
1620 p
= malloc(sizeof(*p
));
1621 p
->next
= dirhash
[i
];
1623 p
->entry
.hashval
= hash
;
1624 p
->entry
.address
= addr
;
1636 for (i
= 0; i
< DIR_HASH_SIZE
; i
++) {
1637 for (p
= dirhash
[i
]; p
; p
= p
->next
) {
1640 if (!sflag
|| id
->ilist
|| v
)
1641 dbprintf("dir ino %lld missing leaf entry for "
1643 id
->ino
, p
->entry
.hashval
,
1657 for (i
= 0; i
< DIR_HASH_SIZE
; i
++) {
1658 for (p
= dirhash
[i
]; p
; p
= n
) {
1670 dirhash
= calloc(DIR_HASH_SIZE
, sizeof(*dirhash
));
1676 xfs_dir2_dataptr_t addr
)
1681 i
= DIR_HASH_FUNC(hash
, addr
);
1682 for (p
= dirhash
[i
]; p
; p
= p
->next
) {
1683 if (p
->entry
.hashval
== hash
&& p
->entry
.address
== addr
) {
1699 xfs_agnumber_t agno
;
1704 agno
= XFS_INO_TO_AGNO(mp
, ino
);
1705 agino
= XFS_INO_TO_AGINO(mp
, ino
);
1706 if (agno
>= mp
->m_sb
.sb_agcount
||
1707 XFS_AGINO_TO_INO(mp
, agno
, agino
) != ino
)
1709 htab
= inodata
[agno
];
1710 ih
= agino
% inodata_hash_size
;
1713 if (ent
->ino
== ino
)
1719 ent
= xcalloc(1, sizeof(*ent
));
1721 ent
->next
= htab
[ih
];
1728 xfs_agnumber_t agno
)
1736 for (i
= 0; i
< inodata_hash_size
; i
++) {
1759 if (mp
->m_sb
.sb_magicnum
!= XFS_SB_MAGIC
) {
1760 dbprintf("bad superblock magic number %x, giving up\n",
1761 mp
->m_sb
.sb_magicnum
);
1766 rt
= mp
->m_sb
.sb_rextents
!= 0;
1767 dbmap
= xmalloc((mp
->m_sb
.sb_agcount
+ rt
) * sizeof(*dbmap
));
1768 inomap
= xmalloc((mp
->m_sb
.sb_agcount
+ rt
) * sizeof(*inomap
));
1769 inodata
= xmalloc(mp
->m_sb
.sb_agcount
* sizeof(*inodata
));
1771 (int)MAX(MIN(mp
->m_sb
.sb_icount
/
1772 (INODATA_AVG_HASH_LENGTH
* mp
->m_sb
.sb_agcount
),
1773 MAX_INODATA_HASH_SIZE
),
1774 MIN_INODATA_HASH_SIZE
);
1775 for (c
= 0; c
< mp
->m_sb
.sb_agcount
; c
++) {
1776 dbmap
[c
] = xcalloc(mp
->m_sb
.sb_agblocks
, sizeof(**dbmap
));
1777 inomap
[c
] = xcalloc(mp
->m_sb
.sb_agblocks
, sizeof(**inomap
));
1778 inodata
[c
] = xcalloc(inodata_hash_size
, sizeof(**inodata
));
1781 dbmap
[c
] = xcalloc(mp
->m_sb
.sb_rblocks
, sizeof(**dbmap
));
1782 inomap
[c
] = xcalloc(mp
->m_sb
.sb_rblocks
, sizeof(**inomap
));
1783 sumfile
= xcalloc(mp
->m_rsumsize
, 1);
1784 sumcompute
= xcalloc(mp
->m_rsumsize
, 1);
1786 nflag
= sflag
= tflag
= verbose
= optind
= 0;
1787 while ((c
= getopt(argc
, argv
, "b:i:npstv")) != EOF
) {
1790 bno
= strtoll(optarg
, NULL
, 10);
1794 ino
= strtoll(optarg
, NULL
, 10);
1813 dbprintf("bad option for blockget command\n");
1817 error
= sbver_err
= serious_error
= 0;
1818 fdblocks
= frextents
= icount
= ifree
= 0;
1819 sbversion
= XFS_SB_VERSION_4
;
1820 if (mp
->m_sb
.sb_inoalignmt
)
1821 sbversion
|= XFS_SB_VERSION_ALIGNBIT
;
1822 if ((mp
->m_sb
.sb_uquotino
&& mp
->m_sb
.sb_uquotino
!= NULLFSINO
) ||
1823 (mp
->m_sb
.sb_gquotino
&& mp
->m_sb
.sb_gquotino
!= NULLFSINO
))
1824 sbversion
|= XFS_SB_VERSION_QUOTABIT
;
1838 id
= find_inode(ino
, 0);
1843 if (id
->name
== NULL
)
1845 path
= xstrdup(id
->name
);
1846 while (id
->parent
) {
1848 if (id
->name
== NULL
)
1850 npath
= prepend_path(path
, id
->name
);
1862 xfs_agnumber_t agno
;
1875 if (!inodata
|| !nflag
) {
1876 dbprintf("must run blockget -n first\n");
1879 security
= optind
= ilist_size
= 0;
1881 while ((c
= getopt(argc
, argv
, "i:s")) != EOF
) {
1884 ino
= strtoll(optarg
, NULL
, 10);
1885 ilist
= xrealloc(ilist
, (ilist_size
+ 1) *
1887 ilist
[ilist_size
++] = ino
;
1893 dbprintf("bad option -%c for ncheck command\n", c
);
1898 for (ilp
= ilist
; ilp
< &ilist
[ilist_size
]; ilp
++) {
1900 if ((p
= inode_name(ino
, &hp
))) {
1901 dbprintf("%11llu %s", ino
, p
);
1911 for (agno
= 0; agno
< mp
->m_sb
.sb_agcount
; agno
++) {
1913 for (i
= 0; i
< inodata_hash_size
; i
++) {
1915 for (hp
= ht
[i
]; hp
; hp
= hp
->next
) {
1916 ino
= XFS_AGINO_TO_INO(mp
, agno
, hp
->ino
);
1917 p
= inode_name(ino
, &id
);
1920 if (!security
|| id
->security
) {
1921 dbprintf("%11llu %s", ino
, p
);
1941 len
= (int)(strlen(oldpath
) + strlen(parent
) + 2);
1942 path
= xmalloc(len
);
1943 snprintf(path
, len
, "%s/%s", parent
, oldpath
);
1948 process_block_dir_v2(
1962 nex
= blkmap_getn(blkmap
, 0, mp
->m_dirblkfsbs
, &bmp
);
1963 v
= id
->ilist
|| verbose
;
1966 dbprintf("block 0 for directory inode %lld is "
1974 make_bbmap(&bbmap
, nex
, bmp
);
1975 set_cur(&typtab
[TYP_DIR
], XFS_FSB_TO_DADDR(mp
, bmp
->startblock
),
1976 mp
->m_dirblkfsbs
* blkbb
, DB_RING_IGN
, nex
> 1 ? &bbmap
: NULL
);
1977 for (x
= 0; !v
&& x
< nex
; x
++) {
1978 for (b
= bmp
[x
].startblock
;
1979 !v
&& b
< bmp
[x
].startblock
+ bmp
[x
].blockcount
;
1984 if (iocur_top
->data
== NULL
) {
1985 if (!sflag
|| id
->ilist
|| v
)
1986 dbprintf("can't read block 0 for directory inode "
1993 parent
= process_data_dir_v2(dot
, dotdot
, id
, v
, mp
->m_dirdatablk
,
1995 dir_hash_check(id
, v
);
2002 process_bmbt_reclist(
2003 xfs_bmbt_rec_32_t
*rp
,
2010 xfs_agblock_t agbno
;
2011 xfs_agnumber_t agno
;
2017 xfs_agblock_t iagbno
;
2018 xfs_agnumber_t iagno
;
2025 v
= verbose
|| id
->ilist
;
2026 iagno
= XFS_INO_TO_AGNO(mp
, id
->ino
);
2027 iagbno
= XFS_INO_TO_AGBNO(mp
, id
->ino
);
2028 for (i
= 0; i
< numrecs
; i
++, rp
++) {
2029 convert_extent((xfs_bmbt_rec_64_t
*)rp
, &o
, &s
, &c
, &f
);
2031 dbprintf("inode %lld extent [%lld,%lld,%lld,%d]\n",
2032 id
->ino
, o
, s
, c
, f
);
2033 if (!sflag
&& i
> 0 && op
+ cp
> o
)
2034 dbprintf("bmap rec out of order, inode %lld entry %d\n",
2038 if (type
== DBM_RTDATA
) {
2039 if (!sflag
&& s
>= mp
->m_sb
.sb_rblocks
) {
2040 dbprintf("inode %lld bad rt block number %lld, "
2045 } else if (!sflag
) {
2046 agno
= XFS_FSB_TO_AGNO(mp
, s
);
2047 agbno
= XFS_FSB_TO_AGBNO(mp
, s
);
2048 if (agno
>= mp
->m_sb
.sb_agcount
||
2049 agbno
>= mp
->m_sb
.sb_agblocks
) {
2050 dbprintf("inode %lld bad block number %lld "
2051 "[%d,%d], offset %lld\n",
2052 id
->ino
, s
, agno
, agbno
, o
);
2055 if (agbno
+ c
- 1 >= mp
->m_sb
.sb_agblocks
) {
2056 dbprintf("inode %lld bad block number %lld "
2057 "[%d,%d], offset %lld\n",
2058 id
->ino
, s
+ c
- 1, agno
,
2059 agbno
+ (xfs_agblock_t
)c
- 1, o
);
2063 if (blkmapp
&& *blkmapp
)
2064 blkmap_set_ext(blkmapp
, (xfs_fileoff_t
)o
,
2065 (xfs_fsblock_t
)s
, (xfs_extlen_t
)c
);
2066 if (type
== DBM_RTDATA
) {
2067 set_rdbmap((xfs_fsblock_t
)s
, (xfs_extlen_t
)c
,
2069 set_rinomap((xfs_fsblock_t
)s
, (xfs_extlen_t
)c
, id
);
2070 for (b
= (xfs_fsblock_t
)s
;
2071 blist_size
&& b
< s
+ c
;
2074 dbprintf("inode %lld block %lld at "
2076 id
->ino
, (xfs_dfsbno_t
)b
, o
);
2079 agno
= XFS_FSB_TO_AGNO(mp
, (xfs_fsblock_t
)s
);
2080 agbno
= XFS_FSB_TO_AGBNO(mp
, (xfs_fsblock_t
)s
);
2081 set_dbmap(agno
, agbno
, (xfs_extlen_t
)c
, type
, iagno
,
2083 set_inomap(agno
, agbno
, (xfs_extlen_t
)c
, id
);
2084 for (b
= (xfs_fsblock_t
)s
;
2085 blist_size
&& b
< s
+ c
;
2086 b
++, o
++, agbno
++) {
2088 dbprintf("inode %lld block %lld at "
2090 id
->ino
, (xfs_dfsbno_t
)b
, o
);
2102 xfs_drfsbno_t
*totd
,
2103 xfs_drfsbno_t
*toti
,
2108 xfs_bmdr_block_t
*dib
;
2111 xfs_bmbt_rec_32_t
*rp
;
2113 dib
= (xfs_bmdr_block_t
*)XFS_DFORK_PTR(dip
, whichfork
);
2114 if (INT_GET(dib
->bb_level
, ARCH_CONVERT
) >= XFS_BM_MAXLEVELS(mp
, whichfork
)) {
2115 if (!sflag
|| id
->ilist
)
2116 dbprintf("level for ino %lld %s fork bmap root too "
2119 whichfork
== XFS_DATA_FORK
? "data" : "attr",
2120 INT_GET(dib
->bb_level
, ARCH_CONVERT
));
2124 if (INT_GET(dib
->bb_numrecs
, ARCH_CONVERT
) >
2125 XFS_BTREE_BLOCK_MAXRECS(XFS_DFORK_SIZE_HOST(dip
, mp
, whichfork
),
2126 xfs_bmdr
, INT_GET(dib
->bb_level
, ARCH_CONVERT
) == 0)) {
2127 if (!sflag
|| id
->ilist
)
2128 dbprintf("numrecs for ino %lld %s fork bmap root too "
2131 whichfork
== XFS_DATA_FORK
? "data" : "attr",
2132 INT_GET(dib
->bb_numrecs
, ARCH_CONVERT
));
2136 if (INT_GET(dib
->bb_level
, ARCH_CONVERT
) == 0) {
2137 rp
= (xfs_bmbt_rec_32_t
*)XFS_BTREE_REC_ADDR(
2138 XFS_DFORK_SIZE_HOST(dip
, mp
, whichfork
),
2140 XFS_BTREE_BLOCK_MAXRECS(XFS_DFORK_SIZE(dip
, mp
,
2143 process_bmbt_reclist(rp
, INT_GET(dib
->bb_numrecs
, ARCH_CONVERT
), type
, id
, totd
,
2145 *nex
+= INT_GET(dib
->bb_numrecs
, ARCH_CONVERT
);
2148 pp
= XFS_BTREE_PTR_ADDR(XFS_DFORK_SIZE_HOST(dip
, mp
, whichfork
),
2150 XFS_BTREE_BLOCK_MAXRECS(XFS_DFORK_SIZE(dip
, mp
,
2153 for (i
= 0; i
< INT_GET(dib
->bb_numrecs
, ARCH_CONVERT
); i
++)
2154 scan_lbtree((xfs_fsblock_t
)INT_GET(pp
[i
], ARCH_CONVERT
), INT_GET(dib
->bb_level
, ARCH_CONVERT
),
2155 scanfunc_bmap
, type
, id
, totd
, toti
, nex
,
2157 whichfork
== XFS_DATA_FORK
?
2158 TYP_BMAPBTD
: TYP_BMAPBTA
);
2161 XFS_DFORK_SIZE_HOST(dip
, mp
, whichfork
) / sizeof(xfs_bmbt_rec_t
)) {
2162 if (!sflag
|| id
->ilist
)
2163 dbprintf("extent count for ino %lld %s fork too low "
2164 "(%d) for file format\n",
2166 whichfork
== XFS_DATA_FORK
? "data" : "attr",
2173 process_data_dir_v2(
2179 freetab_t
**freetabp
)
2181 xfs_dir2_dataptr_t addr
;
2182 xfs_dir2_data_free_t
*bf
;
2184 xfs_dir2_block_t
*block
;
2185 xfs_dir2_block_tail_t
*btp
= NULL
;
2188 xfs_dir2_data_t
*data
;
2190 xfs_dir2_data_entry_t
*dep
;
2191 xfs_dir2_data_free_t
*dfp
;
2192 xfs_dir2_data_unused_t
*dup
;
2200 xfs_dir2_leaf_entry_t
*lep
= NULL
;
2202 xfs_ino_t parent
= 0;
2206 xfs_dir2_data_off_t
*tagp
;
2208 data
= iocur_top
->data
;
2209 block
= iocur_top
->data
;
2210 if (INT_GET(block
->hdr
.magic
, ARCH_CONVERT
) != XFS_DIR2_BLOCK_MAGIC
&&
2211 INT_GET(data
->hdr
.magic
, ARCH_CONVERT
) != XFS_DIR2_DATA_MAGIC
) {
2213 dbprintf("bad directory data magic # %#x for dir ino "
2215 INT_GET(data
->hdr
.magic
, ARCH_CONVERT
), id
->ino
, dabno
);
2219 db
= XFS_DIR2_DA_TO_DB(mp
, dabno
);
2220 bf
= data
->hdr
.bestfree
;
2221 ptr
= (char *)data
->u
;
2222 if (INT_GET(block
->hdr
.magic
, ARCH_CONVERT
) == XFS_DIR2_BLOCK_MAGIC
) {
2223 btp
= XFS_DIR2_BLOCK_TAIL_P(mp
, block
);
2224 lep
= XFS_DIR2_BLOCK_LEAF_P(btp
);
2225 endptr
= (char *)lep
;
2226 if (endptr
<= ptr
|| endptr
> (char *)btp
) {
2227 endptr
= (char *)data
+ mp
->m_dirblksize
;
2230 dbprintf("bad block directory tail for dir ino "
2236 endptr
= (char *)data
+ mp
->m_dirblksize
;
2237 bf_err
= lastfree_err
= tag_err
= 0;
2238 count
= lastfree
= freeseen
= 0;
2239 if (INT_GET(bf
[0].length
, ARCH_CONVERT
) == 0) {
2240 bf_err
+= INT_GET(bf
[0].offset
, ARCH_CONVERT
) != 0;
2243 if (INT_GET(bf
[1].length
, ARCH_CONVERT
) == 0) {
2244 bf_err
+= INT_GET(bf
[1].offset
, ARCH_CONVERT
) != 0;
2247 if (INT_GET(bf
[2].length
, ARCH_CONVERT
) == 0) {
2248 bf_err
+= INT_GET(bf
[2].offset
, ARCH_CONVERT
) != 0;
2251 bf_err
+= INT_GET(bf
[0].length
, ARCH_CONVERT
) < INT_GET(bf
[1].length
, ARCH_CONVERT
);
2252 bf_err
+= INT_GET(bf
[1].length
, ARCH_CONVERT
) < INT_GET(bf
[2].length
, ARCH_CONVERT
);
2254 freetab
= *freetabp
;
2255 if (freetab
->naents
<= db
) {
2256 *freetabp
= freetab
=
2257 realloc(freetab
, FREETAB_SIZE(db
+ 1));
2258 for (i
= freetab
->naents
; i
< db
; i
++)
2259 freetab
->ents
[i
] = NULLDATAOFF
;
2260 freetab
->naents
= db
+ 1;
2262 if (freetab
->nents
< db
+ 1)
2263 freetab
->nents
= db
+ 1;
2264 freetab
->ents
[db
] = INT_GET(bf
[0].length
, ARCH_CONVERT
);
2266 while (ptr
< endptr
) {
2267 dup
= (xfs_dir2_data_unused_t
*)ptr
;
2268 if (INT_GET(dup
->freetag
, ARCH_CONVERT
) == XFS_DIR2_DATA_FREE_TAG
) {
2269 lastfree_err
+= lastfree
!= 0;
2270 if ((INT_GET(dup
->length
, ARCH_CONVERT
) & (XFS_DIR2_DATA_ALIGN
- 1)) ||
2271 INT_GET(dup
->length
, ARCH_CONVERT
) == 0 ||
2272 (char *)(tagp
= XFS_DIR2_DATA_UNUSED_TAG_P(dup
)) >=
2275 dbprintf("dir %lld block %d bad free "
2283 tag_err
+= INT_GET(*tagp
, ARCH_CONVERT
) != (char *)dup
- (char *)data
;
2284 dfp
= process_data_dir_v2_freefind(data
, dup
);
2286 i
= (int)(dfp
- bf
);
2287 bf_err
+= (freeseen
& (1 << i
)) != 0;
2290 bf_err
+= INT_GET(dup
->length
, ARCH_CONVERT
) > INT_GET(bf
[2].length
, ARCH_CONVERT
);
2291 ptr
+= INT_GET(dup
->length
, ARCH_CONVERT
);
2295 dep
= (xfs_dir2_data_entry_t
*)dup
;
2296 if (dep
->namelen
== 0) {
2298 dbprintf("dir %lld block %d zero length entry "
2301 (int)((char *)dep
- (char *)data
));
2304 tagp
= XFS_DIR2_DATA_ENTRY_TAG_P(dep
);
2305 if ((char *)tagp
>= endptr
) {
2307 dbprintf("dir %lld block %d bad entry at %d\n",
2309 (int)((char *)dep
- (char *)data
));
2313 tag_err
+= INT_GET(*tagp
, ARCH_CONVERT
) != (char *)dep
- (char *)data
;
2314 addr
= XFS_DIR2_DB_OFF_TO_DATAPTR(mp
, db
,
2315 (char *)dep
- (char *)data
);
2316 hash
= libxfs_da_hashname((char *)dep
->name
, dep
->namelen
);
2317 dir_hash_add(hash
, addr
);
2318 ptr
+= XFS_DIR2_DATA_ENTSIZE(dep
->namelen
);
2321 lino
= INT_GET(dep
->inumber
, ARCH_CONVERT
);
2322 cid
= find_inode(lino
, 1);
2324 dbprintf("dir %lld block %d entry %*.*s %lld\n",
2325 id
->ino
, dabno
, dep
->namelen
, dep
->namelen
,
2331 dbprintf("dir %lld block %d entry %*.*s bad "
2332 "inode number %lld\n",
2333 id
->ino
, dabno
, dep
->namelen
,
2334 dep
->namelen
, dep
->name
, lino
);
2337 if (dep
->namelen
== 2 && dep
->name
[0] == '.' &&
2338 dep
->name
[1] == '.') {
2341 dbprintf("multiple .. entries in dir "
2342 "%lld (%lld, %lld)\n",
2343 id
->ino
, parent
, lino
);
2346 parent
= cid
? lino
: NULLFSINO
;
2348 } else if (dep
->namelen
!= 1 || dep
->name
[0] != '.') {
2352 addname_inode(cid
, (char *)dep
->name
,
2356 if (lino
!= id
->ino
) {
2358 dbprintf("dir %lld entry . inode "
2359 "number mismatch (%lld)\n",
2366 if (INT_GET(data
->hdr
.magic
, ARCH_CONVERT
) == XFS_DIR2_BLOCK_MAGIC
) {
2367 endptr
= (char *)data
+ mp
->m_dirblksize
;
2368 for (i
= stale
= 0; lep
&& i
< INT_GET(btp
->count
, ARCH_CONVERT
); i
++) {
2369 if ((char *)&lep
[i
] >= endptr
) {
2371 dbprintf("dir %lld block %d bad count "
2373 id
->ino
, dabno
, INT_GET(btp
->count
, ARCH_CONVERT
));
2377 if (INT_GET(lep
[i
].address
, ARCH_CONVERT
) == XFS_DIR2_NULL_DATAPTR
)
2379 else if (dir_hash_see(INT_GET(lep
[i
].hashval
, ARCH_CONVERT
), INT_GET(lep
[i
].address
, ARCH_CONVERT
))) {
2381 dbprintf("dir %lld block %d extra leaf "
2383 id
->ino
, dabno
, INT_GET(lep
[i
].hashval
, ARCH_CONVERT
),
2384 INT_GET(lep
[i
].address
, ARCH_CONVERT
));
2389 bf_err
+= freeseen
!= 7;
2392 dbprintf("dir %lld block %d bad bestfree data\n",
2396 if (INT_GET(data
->hdr
.magic
, ARCH_CONVERT
) == XFS_DIR2_BLOCK_MAGIC
&&
2397 count
!= INT_GET(btp
->count
, ARCH_CONVERT
) - INT_GET(btp
->stale
, ARCH_CONVERT
)) {
2399 dbprintf("dir %lld block %d bad block tail count %d "
2401 id
->ino
, dabno
, INT_GET(btp
->count
, ARCH_CONVERT
), INT_GET(btp
->stale
, ARCH_CONVERT
));
2404 if (INT_GET(data
->hdr
.magic
, ARCH_CONVERT
) == XFS_DIR2_BLOCK_MAGIC
&& stale
!= INT_GET(btp
->stale
, ARCH_CONVERT
)) {
2406 dbprintf("dir %lld block %d bad stale tail count %d\n",
2407 id
->ino
, dabno
, INT_GET(btp
->stale
, ARCH_CONVERT
));
2412 dbprintf("dir %lld block %d consecutive free entries\n",
2418 dbprintf("dir %lld block %d entry/unused tag "
2426 static xfs_dir2_data_free_t
*
2427 process_data_dir_v2_freefind(
2428 xfs_dir2_data_t
*data
,
2429 xfs_dir2_data_unused_t
*dup
)
2431 xfs_dir2_data_free_t
*dfp
;
2432 xfs_dir2_data_aoff_t off
;
2434 off
= (xfs_dir2_data_aoff_t
)((char *)dup
- (char *)data
);
2435 if (INT_GET(dup
->length
, ARCH_CONVERT
) < INT_GET(data
->hdr
.bestfree
[XFS_DIR2_DATA_FD_COUNT
- 1].length
, ARCH_CONVERT
))
2437 for (dfp
= &data
->hdr
.bestfree
[0];
2438 dfp
< &data
->hdr
.bestfree
[XFS_DIR2_DATA_FD_COUNT
];
2440 if (INT_GET(dfp
->offset
, ARCH_CONVERT
) == 0)
2442 if (INT_GET(dfp
->offset
, ARCH_CONVERT
) == off
)
2460 if (XFS_DIR_IS_V2(mp
)) {
2461 if (process_dir_v2(dip
, blkmap
, &dot
, &dotdot
, id
, &parent
))
2465 if (process_dir_v1(dip
, blkmap
, &dot
, &dotdot
, id
, &parent
))
2468 bno
= XFS_INO_TO_FSB(mp
, id
->ino
);
2470 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2471 dbprintf("no . entry for directory %lld\n", id
->ino
);
2475 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2476 dbprintf("no .. entry for directory %lld\n", id
->ino
);
2478 } else if (parent
== id
->ino
&& id
->ino
!= mp
->m_sb
.sb_rootino
) {
2479 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2480 dbprintf(". and .. same for non-root directory %lld\n",
2483 } else if (id
->ino
== mp
->m_sb
.sb_rootino
&& id
->ino
!= parent
) {
2484 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2485 dbprintf("root directory %lld has .. %lld\n", id
->ino
,
2488 } else if (parent
!= NULLFSINO
&& id
->ino
!= parent
)
2489 addparent_inode(id
, parent
);
2501 if (dip
->di_core
.di_size
<= XFS_DFORK_DSIZE_HOST(dip
, mp
) &&
2502 dip
->di_core
.di_format
== XFS_DINODE_FMT_LOCAL
)
2504 process_shortform_dir_v1(dip
, dot
, dotdot
, id
);
2505 else if (dip
->di_core
.di_size
== XFS_LBSIZE(mp
) &&
2506 (dip
->di_core
.di_format
== XFS_DINODE_FMT_EXTENTS
||
2507 dip
->di_core
.di_format
== XFS_DINODE_FMT_BTREE
))
2508 *parent
= process_leaf_dir_v1(blkmap
, dot
, dotdot
, id
);
2509 else if (dip
->di_core
.di_size
>= XFS_LBSIZE(mp
) &&
2510 (dip
->di_core
.di_format
== XFS_DINODE_FMT_EXTENTS
||
2511 dip
->di_core
.di_format
== XFS_DINODE_FMT_BTREE
))
2512 *parent
= process_node_dir_v1(blkmap
, dot
, dotdot
, id
);
2514 dbprintf("bad size (%lld) or format (%d) for directory inode "
2516 dip
->di_core
.di_size
, (int)dip
->di_core
.di_format
,
2533 xfs_fileoff_t last
= 0;
2536 last
= blkmap_last_off(blkmap
);
2537 if (dip
->di_core
.di_size
<= XFS_DFORK_DSIZE_HOST(dip
, mp
) &&
2538 dip
->di_core
.di_format
== XFS_DINODE_FMT_LOCAL
)
2539 *parent
= process_sf_dir_v2(dip
, dot
, dotdot
, id
);
2540 else if (last
== mp
->m_dirblkfsbs
&&
2541 (dip
->di_core
.di_format
== XFS_DINODE_FMT_EXTENTS
||
2542 dip
->di_core
.di_format
== XFS_DINODE_FMT_BTREE
))
2543 *parent
= process_block_dir_v2(blkmap
, dot
, dotdot
, id
);
2544 else if (last
>= mp
->m_dirleafblk
+ mp
->m_dirblkfsbs
&&
2545 (dip
->di_core
.di_format
== XFS_DINODE_FMT_EXTENTS
||
2546 dip
->di_core
.di_format
== XFS_DINODE_FMT_BTREE
))
2547 *parent
= process_leaf_node_dir_v2(blkmap
, dot
, dotdot
, id
,
2548 dip
->di_core
.di_size
);
2550 dbprintf("bad size (%lld) or format (%d) for directory inode "
2552 dip
->di_core
.di_size
, (int)dip
->di_core
.di_format
,
2566 xfs_drfsbno_t
*totd
,
2567 xfs_drfsbno_t
*toti
,
2572 xfs_bmbt_rec_32_t
*rp
;
2574 rp
= (xfs_bmbt_rec_32_t
*)XFS_DFORK_PTR(dip
, whichfork
);
2575 *nex
= XFS_DFORK_NEXTENTS_HOST(dip
, whichfork
);
2578 XFS_DFORK_SIZE_HOST(dip
, mp
, whichfork
) / sizeof(xfs_bmbt_rec_32_t
)) {
2579 if (!sflag
|| id
->ilist
)
2580 dbprintf("bad number of extents %d for inode %lld\n",
2585 process_bmbt_reclist(rp
, *nex
, type
, id
, totd
, blkmapp
);
2596 xfs_fsblock_t bno
= 0;
2597 xfs_dinode_core_t tdic
;
2598 xfs_dinode_core_t
*dic
;
2599 inodata_t
*id
= NULL
;
2601 xfs_extnum_t nextents
= 0;
2604 xfs_drfsbno_t totblocks
;
2605 xfs_drfsbno_t totdblocks
= 0;
2606 xfs_drfsbno_t totiblocks
= 0;
2608 xfs_extnum_t anextents
= 0;
2609 xfs_drfsbno_t atotdblocks
= 0;
2610 xfs_drfsbno_t atotiblocks
= 0;
2615 static char okfmts
[] = {
2616 0, /* type 0 unused */
2617 1 << XFS_DINODE_FMT_DEV
, /* FIFO */
2618 1 << XFS_DINODE_FMT_DEV
, /* CHR */
2619 0, /* type 3 unused */
2620 (1 << XFS_DINODE_FMT_LOCAL
) |
2621 (1 << XFS_DINODE_FMT_EXTENTS
) |
2622 (1 << XFS_DINODE_FMT_BTREE
), /* DIR */
2623 0, /* type 5 unused */
2624 1 << XFS_DINODE_FMT_DEV
, /* BLK */
2625 0, /* type 7 unused */
2626 (1 << XFS_DINODE_FMT_EXTENTS
) |
2627 (1 << XFS_DINODE_FMT_BTREE
), /* REG */
2628 0, /* type 9 unused */
2629 (1 << XFS_DINODE_FMT_LOCAL
) |
2630 (1 << XFS_DINODE_FMT_EXTENTS
), /* LNK */
2631 0, /* type 11 unused */
2632 1 << XFS_DINODE_FMT_DEV
, /* SOCK */
2633 0, /* type 13 unused */
2634 1 << XFS_DINODE_FMT_UUID
, /* MNT */
2635 0 /* type 15 unused */
2637 static char *fmtnames
[] = {
2638 "dev", "local", "extents", "btree", "uuid"
2641 /* convert the core, then copy it back into the inode */
2642 libxfs_xlate_dinode_core((xfs_caddr_t
)&dip
->di_core
, &tdic
, 1);
2643 memcpy(&dip
->di_core
, &tdic
, sizeof(xfs_dinode_core_t
));
2646 ino
= XFS_AGINO_TO_INO(mp
, INT_GET(agf
->agf_seqno
, ARCH_CONVERT
), agino
);
2648 id
= find_inode(ino
, 1);
2649 bno
= XFS_INO_TO_FSB(mp
, ino
);
2652 if (dic
->di_magic
!= XFS_DINODE_MAGIC
) {
2653 if (!sflag
|| isfree
|| id
->ilist
|| CHECK_BLIST(bno
))
2654 dbprintf("bad magic number %#x for inode %lld\n",
2655 dic
->di_magic
, ino
);
2659 if (!XFS_DINODE_GOOD_VERSION(dic
->di_version
)) {
2660 if (!sflag
|| isfree
|| id
->ilist
|| CHECK_BLIST(bno
))
2661 dbprintf("bad version number %#x for inode %lld\n",
2662 dic
->di_version
, ino
);
2667 if (dic
->di_nblocks
!= 0) {
2668 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2669 dbprintf("bad nblocks %lld for free inode "
2671 dic
->di_nblocks
, ino
);
2674 if (dic
->di_version
== XFS_DINODE_VERSION_1
)
2675 nlink
= dic
->di_onlink
;
2677 nlink
= dic
->di_nlink
;
2679 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2680 dbprintf("bad nlink %d for free inode %lld\n",
2684 if (dic
->di_mode
!= 0) {
2685 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2686 dbprintf("bad mode %#o for free inode %lld\n",
2693 * di_mode is a 16-bit uint so no need to check the < 0 case
2695 if ((((dic
->di_mode
& S_IFMT
) >> 12) > 15) ||
2696 (!(okfmts
[(dic
->di_mode
& S_IFMT
) >> 12] & (1 << dic
->di_format
)))) {
2697 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2698 dbprintf("bad format %d for inode %lld type %#o\n",
2699 dic
->di_format
, id
->ino
, dic
->di_mode
& S_IFMT
);
2703 if ((unsigned int)XFS_DFORK_ASIZE_HOST(dip
, mp
) >= XFS_LITINO(mp
)) {
2704 if (!sflag
|| id
->ilist
)
2705 dbprintf("bad fork offset %d for inode %lld\n",
2706 dic
->di_forkoff
, id
->ino
);
2710 if ((unsigned int)dic
->di_aformat
> XFS_DINODE_FMT_BTREE
) {
2711 if (!sflag
|| id
->ilist
)
2712 dbprintf("bad attribute format %d for inode %lld\n",
2713 dic
->di_aformat
, id
->ino
);
2717 if (verbose
|| id
->ilist
|| CHECK_BLIST(bno
))
2718 dbprintf("inode %lld mode %#o fmt %s "
2720 "nex %d anex %d nblk %lld sz %lld%s%s%s%s%s%s%s\n",
2721 id
->ino
, dic
->di_mode
, fmtnames
[(int)dic
->di_format
],
2722 fmtnames
[(int)dic
->di_aformat
],
2725 dic
->di_nblocks
, dic
->di_size
,
2726 dic
->di_flags
& XFS_DIFLAG_REALTIME
? " rt" : "",
2727 dic
->di_flags
& XFS_DIFLAG_PREALLOC
? " pre" : "",
2728 dic
->di_flags
& XFS_DIFLAG_IMMUTABLE
? " imm" : "",
2729 dic
->di_flags
& XFS_DIFLAG_APPEND
? " app" : "",
2730 dic
->di_flags
& XFS_DIFLAG_SYNC
? " syn" : "",
2731 dic
->di_flags
& XFS_DIFLAG_NOATIME
? " noa" : "",
2732 dic
->di_flags
& XFS_DIFLAG_NODUMP
? " nod" : "");
2734 switch (dic
->di_mode
& S_IFMT
) {
2737 if (dic
->di_format
== XFS_DINODE_FMT_LOCAL
)
2739 blkmap
= blkmap_alloc(dic
->di_nextents
);
2742 if (dic
->di_flags
& XFS_DIFLAG_REALTIME
)
2744 else if (id
->ino
== mp
->m_sb
.sb_rbmino
) {
2745 type
= DBM_RTBITMAP
;
2746 blkmap
= blkmap_alloc(dic
->di_nextents
);
2748 } else if (id
->ino
== mp
->m_sb
.sb_rsumino
) {
2750 blkmap
= blkmap_alloc(dic
->di_nextents
);
2753 else if (id
->ino
== mp
->m_sb
.sb_uquotino
||
2754 id
->ino
== mp
->m_sb
.sb_gquotino
) {
2756 blkmap
= blkmap_alloc(dic
->di_nextents
);
2761 if (dic
->di_mode
& (S_ISUID
| S_ISGID
))
2772 if (dic
->di_version
== XFS_DINODE_VERSION_1
)
2773 setlink_inode(id
, dic
->di_onlink
, type
== DBM_DIR
, security
);
2775 sbversion
|= XFS_SB_VERSION_NLINKBIT
;
2776 setlink_inode(id
, dic
->di_nlink
, type
== DBM_DIR
, security
);
2778 switch (dic
->di_format
) {
2779 case XFS_DINODE_FMT_LOCAL
:
2780 process_lclinode(id
, dip
, type
, &totdblocks
, &totiblocks
,
2781 &nextents
, &blkmap
, XFS_DATA_FORK
);
2783 case XFS_DINODE_FMT_EXTENTS
:
2784 process_exinode(id
, dip
, type
, &totdblocks
, &totiblocks
,
2785 &nextents
, &blkmap
, XFS_DATA_FORK
);
2787 case XFS_DINODE_FMT_BTREE
:
2788 process_btinode(id
, dip
, type
, &totdblocks
, &totiblocks
,
2789 &nextents
, &blkmap
, XFS_DATA_FORK
);
2792 if (XFS_DFORK_Q(dip
)) {
2793 sbversion
|= XFS_SB_VERSION_ATTRBIT
;
2794 switch (dic
->di_aformat
) {
2795 case XFS_DINODE_FMT_LOCAL
:
2796 process_lclinode(id
, dip
, DBM_ATTR
, &atotdblocks
,
2797 &atotiblocks
, &anextents
, NULL
, XFS_ATTR_FORK
);
2799 case XFS_DINODE_FMT_EXTENTS
:
2800 process_exinode(id
, dip
, DBM_ATTR
, &atotdblocks
,
2801 &atotiblocks
, &anextents
, NULL
, XFS_ATTR_FORK
);
2803 case XFS_DINODE_FMT_BTREE
:
2804 process_btinode(id
, dip
, DBM_ATTR
, &atotdblocks
,
2805 &atotiblocks
, &anextents
, NULL
, XFS_ATTR_FORK
);
2809 if (qgdo
|| qpdo
|| qudo
) {
2817 bc
= totdblocks
+ totiblocks
+
2818 atotdblocks
+ atotiblocks
;
2822 bc
= totiblocks
+ atotdblocks
+ atotiblocks
;
2830 dqprid
= dic
->di_projid
; /* dquot ID is u32 */
2831 quota_add(&dqprid
, &dic
->di_gid
, &dic
->di_uid
,
2835 totblocks
= totdblocks
+ totiblocks
+ atotdblocks
+ atotiblocks
;
2836 if (totblocks
!= dic
->di_nblocks
) {
2837 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2838 dbprintf("bad nblocks %lld for inode %lld, counted "
2840 dic
->di_nblocks
, id
->ino
, totblocks
);
2843 if (nextents
!= dic
->di_nextents
) {
2844 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2845 dbprintf("bad nextents %d for inode %lld, counted %d\n",
2846 dic
->di_nextents
, id
->ino
, nextents
);
2849 if (anextents
!= dic
->di_anextents
) {
2850 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2851 dbprintf("bad anextents %d for inode %lld, counted "
2853 dic
->di_anextents
, id
->ino
, anextents
);
2856 if (type
== DBM_DIR
)
2857 process_dir(dip
, blkmap
, id
);
2858 else if (type
== DBM_RTBITMAP
)
2859 process_rtbitmap(blkmap
);
2860 else if (type
== DBM_RTSUM
)
2861 process_rtsummary(blkmap
);
2863 * If the CHKD flag is not set, this can legitimately contain garbage;
2864 * xfs_repair may have cleared that bit.
2866 else if (type
== DBM_QUOTA
) {
2867 if (id
->ino
== mp
->m_sb
.sb_uquotino
&&
2868 (mp
->m_sb
.sb_qflags
& XFS_UQUOTA_ACCT
) &&
2869 (mp
->m_sb
.sb_qflags
& XFS_UQUOTA_CHKD
))
2870 process_quota(IS_USER_QUOTA
, id
, blkmap
);
2871 else if (id
->ino
== mp
->m_sb
.sb_gquotino
&&
2872 (mp
->m_sb
.sb_qflags
& XFS_GQUOTA_ACCT
) &&
2873 (mp
->m_sb
.sb_qflags
& XFS_OQUOTA_CHKD
))
2874 process_quota(IS_GROUP_QUOTA
, id
, blkmap
);
2875 else if (id
->ino
== mp
->m_sb
.sb_gquotino
&&
2876 (mp
->m_sb
.sb_qflags
& XFS_PQUOTA_ACCT
) &&
2877 (mp
->m_sb
.sb_qflags
& XFS_OQUOTA_CHKD
))
2878 process_quota(IS_PROJECT_QUOTA
, id
, blkmap
);
2881 blkmap_free(blkmap
);
2890 xfs_drfsbno_t
*totd
,
2891 xfs_drfsbno_t
*toti
,
2896 xfs_attr_shortform_t
*asf
;
2898 xfs_dinode_core_t
*dic
;
2900 dic
= &dip
->di_core
;
2901 bno
= XFS_INO_TO_FSB(mp
, id
->ino
);
2902 if (whichfork
== XFS_DATA_FORK
&&
2903 dic
->di_size
> XFS_DFORK_DSIZE_HOST(dip
, mp
)) {
2904 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2905 dbprintf("local inode %lld data is too large (size "
2907 id
->ino
, dic
->di_size
);
2910 else if (whichfork
== XFS_ATTR_FORK
) {
2911 asf
= (xfs_attr_shortform_t
*)XFS_DFORK_PTR(dip
, whichfork
);
2912 if (INT_GET(asf
->hdr
.totsize
, ARCH_CONVERT
) > XFS_DFORK_ASIZE_HOST(dip
, mp
)) {
2913 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2914 dbprintf("local inode %lld attr is too large "
2916 id
->ino
, INT_GET(asf
->hdr
.totsize
, ARCH_CONVERT
));
2923 process_leaf_dir_v1(
2932 bno
= blkmap_get(blkmap
, 0);
2933 if (bno
== NULLFSBLOCK
) {
2934 if (!sflag
|| id
->ilist
)
2935 dbprintf("block 0 for directory inode %lld is "
2942 set_cur(&typtab
[TYP_DIR
], XFS_FSB_TO_DADDR(mp
, bno
), blkbb
, DB_RING_IGN
,
2944 if (iocur_top
->data
== NULL
) {
2945 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2946 dbprintf("can't read block 0 for directory inode "
2952 parent
= process_leaf_dir_v1_int(dot
, dotdot
, id
);
2958 process_leaf_dir_v1_int(
2965 xfs_dir_leaf_entry_t
*entry
;
2967 xfs_dir_leafblock_t
*leaf
;
2969 xfs_dir_leaf_name_t
*namest
;
2970 xfs_ino_t parent
= 0;
2973 bno
= XFS_DADDR_TO_FSB(mp
, iocur_top
->bb
);
2974 v
= verbose
|| id
->ilist
|| CHECK_BLIST(bno
);
2975 leaf
= iocur_top
->data
;
2976 if (INT_GET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
) != XFS_DIR_LEAF_MAGIC
) {
2977 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2978 dbprintf("bad directory leaf magic # %#x for dir ino "
2980 INT_GET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
), id
->ino
);
2984 entry
= &leaf
->entries
[0];
2985 for (i
= 0; i
< INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
); entry
++, i
++) {
2986 namest
= XFS_DIR_LEAF_NAMESTRUCT(leaf
, INT_GET(entry
->nameidx
, ARCH_CONVERT
));
2987 lino
= XFS_GET_DIR_INO8(namest
->inumber
);
2988 cid
= find_inode(lino
, 1);
2990 dbprintf("dir %lld entry %*.*s %lld\n", id
->ino
,
2991 entry
->namelen
, entry
->namelen
, namest
->name
,
2997 dbprintf("dir %lld entry %*.*s bad inode "
2999 id
->ino
, entry
->namelen
, entry
->namelen
,
3000 namest
->name
, lino
);
3003 if (entry
->namelen
== 2 && namest
->name
[0] == '.' &&
3004 namest
->name
[1] == '.') {
3006 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
3007 dbprintf("multiple .. entries in dir "
3008 "%lld (%lld, %lld)\n",
3009 id
->ino
, parent
, lino
);
3012 parent
= cid
? lino
: NULLFSINO
;
3014 } else if (entry
->namelen
!= 1 || namest
->name
[0] != '.') {
3018 addname_inode(cid
, (char *)namest
->name
,
3022 if (lino
!= id
->ino
) {
3024 dbprintf("dir %lld entry . inode "
3025 "number mismatch (%lld)\n",
3036 process_leaf_node_dir_v2(
3041 xfs_fsize_t dirsize
)
3057 v2
= verbose
|| id
->ilist
;
3060 freetab
= malloc(FREETAB_SIZE(dirsize
/ mp
->m_dirblksize
));
3061 freetab
->naents
= (int)(dirsize
/ mp
->m_dirblksize
);
3063 for (i
= 0; i
< freetab
->naents
; i
++)
3064 freetab
->ents
[i
] = NULLDATAOFF
;
3066 while ((dbno
= blkmap_next_off(blkmap
, dbno
, &t
)) != NULLFILEOFF
) {
3067 nex
= blkmap_getn(blkmap
, dbno
, mp
->m_dirblkfsbs
, &bmp
);
3069 for (v
= v2
, x
= 0; !v
&& x
< nex
; x
++) {
3070 for (b
= bmp
[x
].startblock
;
3071 !v
&& b
< bmp
[x
].startblock
+ bmp
[x
].blockcount
;
3076 dbprintf("dir inode %lld block %u=%llu\n", id
->ino
,
3078 (xfs_dfsbno_t
)bmp
->startblock
);
3081 make_bbmap(&bbmap
, nex
, bmp
);
3082 set_cur(&typtab
[TYP_DIR
], XFS_FSB_TO_DADDR(mp
, bmp
->startblock
),
3083 mp
->m_dirblkfsbs
* blkbb
, DB_RING_IGN
,
3084 nex
> 1 ? &bbmap
: NULL
);
3086 if (iocur_top
->data
== NULL
) {
3088 dbprintf("can't read block %u for directory "
3090 (__uint32_t
)dbno
, id
->ino
);
3093 dbno
+= mp
->m_dirblkfsbs
- 1;
3096 if (dbno
< mp
->m_dirleafblk
) {
3097 lino
= process_data_dir_v2(dot
, dotdot
, id
, v
,
3098 (xfs_dablk_t
)dbno
, &freetab
);
3102 dbprintf("multiple .. entries "
3109 } else if (dbno
< mp
->m_dirfreeblk
) {
3110 process_leaf_node_dir_v2_int(id
, v
, (xfs_dablk_t
)dbno
,
3113 process_leaf_node_dir_v2_free(id
, v
, (xfs_dablk_t
)dbno
,
3117 dbno
+= mp
->m_dirblkfsbs
- 1;
3119 dir_hash_check(id
, v
);
3121 for (i
= 0; i
< freetab
->nents
; i
++) {
3122 if (freetab
->ents
[i
] != NULLDATAOFF
) {
3124 dbprintf("missing free index for data block %d "
3125 "in dir ino %lld\n",
3126 XFS_DIR2_DB_TO_DA(mp
, i
), id
->ino
);
3135 process_leaf_node_dir_v2_free(
3141 xfs_dir2_data_off_t ent
;
3142 xfs_dir2_free_t
*free
;
3147 free
= iocur_top
->data
;
3148 if (INT_GET(free
->hdr
.magic
, ARCH_CONVERT
) != XFS_DIR2_FREE_MAGIC
) {
3150 dbprintf("bad free block magic # %#x for dir ino %lld "
3152 INT_GET(free
->hdr
.magic
, ARCH_CONVERT
), id
->ino
, dabno
);
3156 maxent
= XFS_DIR2_MAX_FREE_BESTS(mp
);
3157 if (INT_GET(free
->hdr
.firstdb
, ARCH_CONVERT
) !=
3158 XFS_DIR2_DA_TO_DB(mp
, dabno
- mp
->m_dirfreeblk
) * maxent
) {
3160 dbprintf("bad free block firstdb %d for dir ino %lld "
3162 INT_GET(free
->hdr
.firstdb
, ARCH_CONVERT
), id
->ino
, dabno
);
3166 if (INT_GET(free
->hdr
.nvalid
, ARCH_CONVERT
) > maxent
|| INT_GET(free
->hdr
.nvalid
, ARCH_CONVERT
) < 0 ||
3167 INT_GET(free
->hdr
.nused
, ARCH_CONVERT
) > maxent
|| INT_GET(free
->hdr
.nused
, ARCH_CONVERT
) < 0 ||
3168 INT_GET(free
->hdr
.nused
, ARCH_CONVERT
) > INT_GET(free
->hdr
.nvalid
, ARCH_CONVERT
)) {
3170 dbprintf("bad free block nvalid/nused %d/%d for dir "
3171 "ino %lld block %d\n",
3172 INT_GET(free
->hdr
.nvalid
, ARCH_CONVERT
), INT_GET(free
->hdr
.nused
, ARCH_CONVERT
), id
->ino
,
3177 for (used
= i
= 0; i
< INT_GET(free
->hdr
.nvalid
, ARCH_CONVERT
); i
++) {
3178 if (freetab
->nents
<= INT_GET(free
->hdr
.firstdb
, ARCH_CONVERT
) + i
)
3181 ent
= freetab
->ents
[INT_GET(free
->hdr
.firstdb
, ARCH_CONVERT
) + i
];
3182 if (ent
!= INT_GET(free
->bests
[i
], ARCH_CONVERT
)) {
3184 dbprintf("bad free block ent %d is %d should "
3185 "be %d for dir ino %lld block %d\n",
3186 i
, INT_GET(free
->bests
[i
], ARCH_CONVERT
), ent
, id
->ino
, dabno
);
3189 if (INT_GET(free
->bests
[i
], ARCH_CONVERT
) != NULLDATAOFF
)
3191 if (ent
!= NULLDATAOFF
)
3192 freetab
->ents
[INT_GET(free
->hdr
.firstdb
, ARCH_CONVERT
) + i
] = NULLDATAOFF
;
3194 if (used
!= INT_GET(free
->hdr
.nused
, ARCH_CONVERT
)) {
3196 dbprintf("bad free block nused %d should be %d for dir "
3197 "ino %lld block %d\n",
3198 INT_GET(free
->hdr
.nused
, ARCH_CONVERT
), used
, id
->ino
, dabno
);
3204 process_leaf_node_dir_v2_int(
3211 xfs_dir2_data_off_t
*lbp
;
3212 xfs_dir2_leaf_t
*leaf
;
3213 xfs_dir2_leaf_entry_t
*lep
;
3214 xfs_dir2_leaf_tail_t
*ltp
;
3215 xfs_da_intnode_t
*node
;
3218 leaf
= iocur_top
->data
;
3219 switch (INT_GET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
)) {
3220 case XFS_DIR2_LEAF1_MAGIC
:
3221 if (INT_GET(leaf
->hdr
.info
.forw
, ARCH_CONVERT
) || INT_GET(leaf
->hdr
.info
.back
, ARCH_CONVERT
)) {
3223 dbprintf("bad leaf block forw/back pointers "
3224 "%d/%d for dir ino %lld block %d\n",
3225 INT_GET(leaf
->hdr
.info
.forw
, ARCH_CONVERT
),
3226 INT_GET(leaf
->hdr
.info
.back
, ARCH_CONVERT
), id
->ino
, dabno
);
3229 if (dabno
!= mp
->m_dirleafblk
) {
3231 dbprintf("single leaf block for dir ino %lld "
3232 "block %d should be at block %d\n",
3234 (xfs_dablk_t
)mp
->m_dirleafblk
);
3237 ltp
= XFS_DIR2_LEAF_TAIL_P(mp
, leaf
);
3238 lbp
= XFS_DIR2_LEAF_BESTS_P(ltp
);
3239 for (i
= 0; i
< INT_GET(ltp
->bestcount
, ARCH_CONVERT
); i
++) {
3240 if (freetab
->nents
<= i
|| freetab
->ents
[i
] != INT_GET(lbp
[i
], ARCH_CONVERT
)) {
3242 dbprintf("bestfree %d for dir ino %lld "
3243 "block %d doesn't match table "
3245 freetab
->nents
<= i
?
3249 XFS_DIR2_DB_TO_DA(mp
, i
),
3250 INT_GET(lbp
[i
], ARCH_CONVERT
));
3252 if (freetab
->nents
> i
)
3253 freetab
->ents
[i
] = NULLDATAOFF
;
3256 case XFS_DIR2_LEAFN_MAGIC
:
3257 /* if it's at the root location then we can check the
3258 * pointers are null XXX */
3260 case XFS_DA_NODE_MAGIC
:
3261 node
= iocur_top
->data
;
3262 if (INT_GET(node
->hdr
.level
, ARCH_CONVERT
) < 1 ||
3263 INT_GET(node
->hdr
.level
, ARCH_CONVERT
) > XFS_DA_NODE_MAXDEPTH
) {
3265 dbprintf("bad node block level %d for dir ino "
3267 INT_GET(node
->hdr
.level
, ARCH_CONVERT
), id
->ino
, dabno
);
3273 dbprintf("bad directory data magic # %#x for dir ino "
3275 INT_GET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
), id
->ino
, dabno
);
3280 for (i
= stale
= 0; i
< INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
); i
++) {
3281 if (INT_GET(lep
[i
].address
, ARCH_CONVERT
) == XFS_DIR2_NULL_DATAPTR
)
3283 else if (dir_hash_see(INT_GET(lep
[i
].hashval
, ARCH_CONVERT
), INT_GET(lep
[i
].address
, ARCH_CONVERT
))) {
3285 dbprintf("dir %lld block %d extra leaf entry "
3287 id
->ino
, dabno
, INT_GET(lep
[i
].hashval
, ARCH_CONVERT
),
3288 INT_GET(lep
[i
].address
, ARCH_CONVERT
));
3292 if (stale
!= INT_GET(leaf
->hdr
.stale
, ARCH_CONVERT
)) {
3294 dbprintf("dir %lld block %d stale mismatch "
3296 id
->ino
, dabno
, stale
,
3297 INT_GET(leaf
->hdr
.stale
, ARCH_CONVERT
));
3303 process_node_dir_v1(
3312 xfs_da_intnode_t
*node
;
3318 v
= verbose
|| id
->ilist
;
3321 while ((dbno
= blkmap_next_off(blkmap
, dbno
, &t
)) != NULLFILEOFF
) {
3322 bno
= blkmap_get(blkmap
, dbno
);
3323 v2
= bno
!= NULLFSBLOCK
&& CHECK_BLIST(bno
);
3324 if (bno
== NULLFSBLOCK
&& dbno
== 0) {
3326 dbprintf("can't read root block for directory "
3332 dbprintf("dir inode %lld block %u=%llu\n", id
->ino
,
3333 (__uint32_t
)dbno
, (xfs_dfsbno_t
)bno
);
3334 if (bno
== NULLFSBLOCK
)
3337 set_cur(&typtab
[TYP_DIR
], XFS_FSB_TO_DADDR(mp
, bno
), blkbb
,
3339 if ((node
= iocur_top
->data
) == NULL
) {
3340 if (!sflag
|| v
|| v2
)
3341 dbprintf("can't read block %u for directory "
3343 (__uint32_t
)dbno
, id
->ino
);
3348 if (INT_GET(node
->hdr
.info
.magic
, ARCH_CONVERT
) == XFS_DA_NODE_MAGIC
)
3350 if (INT_GET(node
->hdr
.info
.magic
, ARCH_CONVERT
) == XFS_DIR_NODE_MAGIC
)
3356 lino
= process_leaf_dir_v1_int(dot
, dotdot
, id
);
3359 if (!sflag
|| v
|| v2
)
3360 dbprintf("multiple .. entries in dir "
3382 u_int8_t exp_flags
= 0;
3393 exp_flags
= XFS_DQ_USER
;
3395 case IS_PROJECT_QUOTA
:
3397 exp_flags
= XFS_DQ_PROJ
;
3399 case IS_GROUP_QUOTA
:
3401 exp_flags
= XFS_DQ_GROUP
;
3407 perblock
= (uint
)(mp
->m_sb
.sb_blocksize
/ sizeof(*dqb
));
3410 while ((qbno
= blkmap_next_off(blkmap
, qbno
, &t
)) !=
3412 bno
= blkmap_get(blkmap
, qbno
);
3413 dqid
= (xfs_dqid_t
)qbno
* perblock
;
3414 cb
= CHECK_BLIST(bno
);
3415 scicb
= !sflag
|| id
->ilist
|| cb
;
3417 set_cur(&typtab
[TYP_DQBLK
], XFS_FSB_TO_DADDR(mp
, bno
), blkbb
,
3419 if ((dqb
= iocur_top
->data
) == NULL
) {
3422 dbprintf("can't read block %lld for %s quota "
3423 "inode (fsblock %lld)\n",
3424 (xfs_dfiloff_t
)qbno
, s
,
3429 for (i
= 0; i
< perblock
; i
++, dqid
++, dqb
++) {
3430 if (verbose
|| id
->ilist
|| cb
)
3431 dbprintf("%s dqblk %lld entry %d id %u bc "
3432 "%lld ic %lld rc %lld\n",
3433 s
, (xfs_dfiloff_t
)qbno
, i
, dqid
,
3434 INT_GET(dqb
->dd_diskdq
.d_bcount
, ARCH_CONVERT
),
3435 INT_GET(dqb
->dd_diskdq
.d_icount
, ARCH_CONVERT
),
3436 INT_GET(dqb
->dd_diskdq
.d_rtbcount
, ARCH_CONVERT
));
3437 if (INT_GET(dqb
->dd_diskdq
.d_magic
, ARCH_CONVERT
) != XFS_DQUOT_MAGIC
) {
3439 dbprintf("bad magic number %#x for %s "
3440 "dqblk %lld entry %d id %u\n",
3441 INT_GET(dqb
->dd_diskdq
.d_magic
, ARCH_CONVERT
), s
,
3442 (xfs_dfiloff_t
)qbno
, i
, dqid
);
3446 if (INT_GET(dqb
->dd_diskdq
.d_version
, ARCH_CONVERT
) != XFS_DQUOT_VERSION
) {
3448 dbprintf("bad version number %#x for "
3449 "%s dqblk %lld entry %d id "
3451 INT_GET(dqb
->dd_diskdq
.d_version
, ARCH_CONVERT
), s
,
3452 (xfs_dfiloff_t
)qbno
, i
, dqid
);
3456 if (INT_GET(dqb
->dd_diskdq
.d_flags
, ARCH_CONVERT
) != exp_flags
) {
3458 dbprintf("bad flags %#x for %s dqblk "
3459 "%lld entry %d id %u\n",
3460 INT_GET(dqb
->dd_diskdq
.d_flags
, ARCH_CONVERT
), s
,
3461 (xfs_dfiloff_t
)qbno
, i
, dqid
);
3465 if (INT_GET(dqb
->dd_diskdq
.d_id
, ARCH_CONVERT
) != dqid
) {
3467 dbprintf("bad id %u for %s dqblk %lld "
3469 INT_GET(dqb
->dd_diskdq
.d_id
, ARCH_CONVERT
), s
,
3470 (xfs_dfiloff_t
)qbno
, i
, dqid
);
3474 quota_add((qtype
== IS_PROJECT_QUOTA
) ? &dqid
: NULL
,
3475 (qtype
== IS_GROUP_QUOTA
) ? &dqid
: NULL
,
3476 (qtype
== IS_USER_QUOTA
) ? &dqid
: NULL
,
3478 INT_GET(dqb
->dd_diskdq
.d_bcount
, ARCH_CONVERT
),
3479 INT_GET(dqb
->dd_diskdq
.d_icount
, ARCH_CONVERT
),
3480 INT_GET(dqb
->dd_diskdq
.d_rtbcount
, ARCH_CONVERT
));
3490 #define xfs_highbit64 libxfs_highbit64 /* for XFS_RTBLOCKLOG macro */
3493 xfs_fileoff_t bmbno
;
3500 xfs_drfsbno_t rtbno
;
3504 xfs_rtword_t
*words
;
3506 bitsperblock
= mp
->m_sb
.sb_blocksize
* NBBY
;
3507 bit
= extno
= prevbit
= start_bmbno
= start_bit
= 0;
3508 bmbno
= NULLFILEOFF
;
3509 while ((bmbno
= blkmap_next_off(blkmap
, bmbno
, &t
)) !=
3511 bno
= blkmap_get(blkmap
, bmbno
);
3512 if (bno
== NULLFSBLOCK
) {
3514 dbprintf("block %lld for rtbitmap inode is "
3516 (xfs_dfiloff_t
)bmbno
);
3521 set_cur(&typtab
[TYP_RTBITMAP
], XFS_FSB_TO_DADDR(mp
, bno
), blkbb
,
3523 if ((words
= iocur_top
->data
) == NULL
) {
3526 dbprintf("can't read block %lld for rtbitmap "
3528 (xfs_dfiloff_t
)bmbno
);
3533 bit
< bitsperblock
&& extno
< mp
->m_sb
.sb_rextents
;
3535 if (xfs_isset(words
, bit
)) {
3536 rtbno
= extno
* mp
->m_sb
.sb_rextsize
;
3537 set_rdbmap(rtbno
, mp
->m_sb
.sb_rextsize
,
3541 start_bmbno
= (int)bmbno
;
3545 } else if (prevbit
== 1) {
3546 len
= ((int)bmbno
- start_bmbno
) *
3547 bitsperblock
+ (bit
- start_bit
);
3548 log
= XFS_RTBLOCKLOG(len
);
3549 offs
= XFS_SUMOFFS(mp
, log
, start_bmbno
);
3555 if (extno
== mp
->m_sb
.sb_rextents
)
3559 len
= ((int)bmbno
- start_bmbno
) * bitsperblock
+
3561 log
= XFS_RTBLOCKLOG(len
);
3562 offs
= XFS_SUMOFFS(mp
, log
, start_bmbno
);
3573 xfs_fileoff_t sumbno
;
3576 sumbno
= NULLFILEOFF
;
3577 while ((sumbno
= blkmap_next_off(blkmap
, sumbno
, &t
)) !=
3579 bno
= blkmap_get(blkmap
, sumbno
);
3580 if (bno
== NULLFSBLOCK
) {
3582 dbprintf("block %lld for rtsummary inode is "
3584 (xfs_dfiloff_t
)sumbno
);
3589 set_cur(&typtab
[TYP_RTSUMMARY
], XFS_FSB_TO_DADDR(mp
, bno
),
3590 blkbb
, DB_RING_IGN
, NULL
);
3591 if ((bytes
= iocur_top
->data
) == NULL
) {
3593 dbprintf("can't read block %lld for rtsummary "
3595 (xfs_dfiloff_t
)sumbno
);
3599 memcpy((char *)sumfile
+ sumbno
* mp
->m_sb
.sb_blocksize
, bytes
,
3600 mp
->m_sb
.sb_blocksize
);
3618 xfs_dir2_sf_entry_t
*sfe
;
3621 sf
= &dip
->di_u
.di_dir2sf
;
3623 v
= verbose
|| id
->ilist
;
3625 dbprintf("dir %lld entry . %lld\n", id
->ino
, id
->ino
);
3627 sfe
= XFS_DIR2_SF_FIRSTENTRY(sf
);
3628 offset
= XFS_DIR2_DATA_FIRST_OFFSET
;
3629 for (i
= INT_GET(sf
->hdr
.count
, ARCH_CONVERT
) - 1, i8
= 0; i
>= 0; i
--) {
3630 if ((__psint_t
)sfe
+ XFS_DIR2_SF_ENTSIZE_BYENTRY(sf
, sfe
) -
3631 (__psint_t
)sf
> dip
->di_core
.di_size
) {
3633 dbprintf("dir %llu bad size in entry at %d\n",
3635 (int)((char *)sfe
- (char *)sf
));
3639 lino
= XFS_DIR2_SF_GET_INUMBER(sf
, XFS_DIR2_SF_INUMBERP(sfe
));
3640 if (lino
> XFS_DIR2_MAX_SHORT_INUM
)
3642 cid
= find_inode(lino
, 1);
3645 dbprintf("dir %lld entry %*.*s bad inode "
3647 id
->ino
, sfe
->namelen
, sfe
->namelen
,
3654 addname_inode(cid
, (char *)sfe
->name
, sfe
->namelen
);
3657 dbprintf("dir %lld entry %*.*s offset %d %lld\n",
3658 id
->ino
, sfe
->namelen
, sfe
->namelen
, sfe
->name
,
3659 XFS_DIR2_SF_GET_OFFSET(sfe
), lino
);
3660 if (XFS_DIR2_SF_GET_OFFSET(sfe
) < offset
) {
3662 dbprintf("dir %lld entry %*.*s bad offset %d\n",
3663 id
->ino
, sfe
->namelen
, sfe
->namelen
,
3664 sfe
->name
, XFS_DIR2_SF_GET_OFFSET(sfe
));
3668 XFS_DIR2_SF_GET_OFFSET(sfe
) +
3669 XFS_DIR2_DATA_ENTSIZE(sfe
->namelen
);
3670 sfe
= XFS_DIR2_SF_NEXTENTRY(sf
, sfe
);
3672 if (i
< 0 && (__psint_t
)sfe
- (__psint_t
)sf
!= dip
->di_core
.di_size
) {
3674 dbprintf("dir %llu size is %lld, should be %u\n",
3675 id
->ino
, dip
->di_core
.di_size
,
3676 (uint
)((char *)sfe
- (char *)sf
));
3679 if (offset
+ (INT_GET(sf
->hdr
.count
, ARCH_CONVERT
) + 2) * sizeof(xfs_dir2_leaf_entry_t
) +
3680 sizeof(xfs_dir2_block_tail_t
) > mp
->m_dirblksize
) {
3682 dbprintf("dir %llu offsets too high\n", id
->ino
);
3685 lino
= XFS_DIR2_SF_GET_INUMBER(sf
, &sf
->hdr
.parent
);
3686 if (lino
> XFS_DIR2_MAX_SHORT_INUM
)
3688 cid
= find_inode(lino
, 1);
3693 dbprintf("dir %lld entry .. bad inode number %lld\n",
3698 dbprintf("dir %lld entry .. %lld\n", id
->ino
, lino
);
3699 if (i8
!= sf
->hdr
.i8count
) {
3701 dbprintf("dir %lld i8count mismatch is %d should be "
3703 id
->ino
, sf
->hdr
.i8count
, i8
);
3707 return cid
? lino
: NULLFSINO
;
3711 process_shortform_dir_v1(
3720 xfs_dir_shortform_t
*sf
;
3721 xfs_dir_sf_entry_t
*sfe
;
3724 sf
= &dip
->di_u
.di_dirsf
;
3726 v
= verbose
|| id
->ilist
;
3728 dbprintf("dir %lld entry . %lld\n", id
->ino
, id
->ino
);
3731 for (i
= INT_GET(sf
->hdr
.count
, ARCH_CONVERT
) - 1; i
>= 0; i
--) {
3732 lino
= XFS_GET_DIR_INO8(sfe
->inumber
);
3733 cid
= find_inode(lino
, 1);
3736 dbprintf("dir %lld entry %*.*s bad inode "
3738 id
->ino
, sfe
->namelen
, sfe
->namelen
,
3745 addname_inode(cid
, (char *)sfe
->name
, sfe
->namelen
);
3748 dbprintf("dir %lld entry %*.*s %lld\n", id
->ino
,
3749 sfe
->namelen
, sfe
->namelen
, sfe
->name
, lino
);
3750 sfe
= XFS_DIR_SF_NEXTENTRY(sfe
);
3752 if ((__psint_t
)sfe
- (__psint_t
)sf
!= dip
->di_core
.di_size
)
3753 dbprintf("dir %llu size is %lld, should be %d\n",
3754 id
->ino
, dip
->di_core
.di_size
,
3755 (int)((char *)sfe
- (char *)sf
));
3756 lino
= XFS_GET_DIR_INO8(sf
->hdr
.parent
);
3757 cid
= find_inode(lino
, 1);
3762 dbprintf("dir %lld entry .. bad inode number %lld\n",
3767 dbprintf("dir %lld entry .. %lld\n", id
->ino
, lino
);
3769 return cid
? lino
: NULLFSINO
;
3782 if (qudo
&& usrid
!= NULL
)
3783 quota_add1(qudata
, *usrid
, dq
, bc
, ic
, rc
);
3784 if (qgdo
&& grpid
!= NULL
)
3785 quota_add1(qgdata
, *grpid
, dq
, bc
, ic
, rc
);
3786 if (qpdo
&& prjid
!= NULL
)
3787 quota_add1(qpdata
, *prjid
, dq
, bc
, ic
, rc
);
3803 qh
= (int)(id
% QDATA_HASH_SIZE
);
3807 qi
= dq
? &qe
->dq
: &qe
->count
;
3815 qe
= xmalloc(sizeof(*qe
));
3817 qi
= dq
? &qe
->dq
: &qe
->count
;
3821 qi
= dq
? &qe
->count
: &qe
->dq
;
3822 qi
->bc
= qi
->ic
= qi
->rc
= 0;
3836 for (i
= 0; i
< QDATA_HASH_SIZE
; i
++) {
3840 if (qp
->count
.bc
!= qp
->dq
.bc
||
3841 qp
->count
.ic
!= qp
->dq
.ic
||
3842 qp
->count
.rc
!= qp
->dq
.rc
) {
3844 dbprintf("%s quota id %u, have/exp",
3846 if (qp
->count
.bc
!= qp
->dq
.bc
)
3847 dbprintf(" bc %lld/%lld",
3850 if (qp
->count
.ic
!= qp
->dq
.ic
)
3851 dbprintf(" ic %lld/%lld",
3854 if (qp
->count
.rc
!= qp
->dq
.rc
)
3855 dbprintf(" rc %lld/%lld",
3872 qudo
= mp
->m_sb
.sb_uquotino
!= 0 &&
3873 mp
->m_sb
.sb_uquotino
!= NULLFSINO
&&
3874 (mp
->m_sb
.sb_qflags
& XFS_UQUOTA_ACCT
) &&
3875 (mp
->m_sb
.sb_qflags
& XFS_UQUOTA_CHKD
);
3876 qgdo
= mp
->m_sb
.sb_gquotino
!= 0 &&
3877 mp
->m_sb
.sb_gquotino
!= NULLFSINO
&&
3878 (mp
->m_sb
.sb_qflags
& XFS_GQUOTA_ACCT
) &&
3879 (mp
->m_sb
.sb_qflags
& XFS_OQUOTA_CHKD
);
3880 qpdo
= mp
->m_sb
.sb_gquotino
!= 0 &&
3881 mp
->m_sb
.sb_gquotino
!= NULLFSINO
&&
3882 (mp
->m_sb
.sb_qflags
& XFS_PQUOTA_ACCT
) &&
3883 (mp
->m_sb
.sb_qflags
& XFS_OQUOTA_CHKD
);
3885 qudata
= xcalloc(QDATA_HASH_SIZE
, sizeof(qdata_t
*));
3887 qgdata
= xcalloc(QDATA_HASH_SIZE
, sizeof(qdata_t
*));
3889 qpdata
= xcalloc(QDATA_HASH_SIZE
, sizeof(qdata_t
*));
3894 xfs_agnumber_t agno
)
3902 agffreeblks
= agflongest
= 0;
3903 agicount
= agifreecount
= 0;
3905 set_cur(&typtab
[TYP_SB
],
3906 XFS_AG_DADDR(mp
, agno
, XFS_SB_DADDR
),
3907 XFS_FSS_TO_BB(mp
, 1), DB_RING_IGN
, NULL
);
3909 if (!iocur_top
->data
) {
3910 dbprintf("can't read superblock for ag %u\n", agno
);
3916 libxfs_xlate_sb(iocur_top
->data
, sb
, 1, XFS_SB_ALL_BITS
);
3918 if (sb
->sb_magicnum
!= XFS_SB_MAGIC
) {
3920 dbprintf("bad sb magic # %#x in ag %u\n",
3921 sb
->sb_magicnum
, agno
);
3924 if (!XFS_SB_GOOD_VERSION(sb
)) {
3926 dbprintf("bad sb version # %#x in ag %u\n",
3927 sb
->sb_versionnum
, agno
);
3931 if (agno
== 0 && sb
->sb_inprogress
!= 0) {
3933 dbprintf("mkfs not completed successfully\n");
3936 set_dbmap(agno
, XFS_SB_BLOCK(mp
), 1, DBM_SB
, agno
, XFS_SB_BLOCK(mp
));
3937 if (sb
->sb_logstart
&& XFS_FSB_TO_AGNO(mp
, sb
->sb_logstart
) == agno
)
3938 set_dbmap(agno
, XFS_FSB_TO_AGBNO(mp
, sb
->sb_logstart
),
3939 sb
->sb_logblocks
, DBM_LOG
, agno
, XFS_SB_BLOCK(mp
));
3941 set_cur(&typtab
[TYP_AGF
],
3942 XFS_AG_DADDR(mp
, agno
, XFS_AGF_DADDR(mp
)),
3943 XFS_FSS_TO_BB(mp
, 1), DB_RING_IGN
, NULL
);
3944 if ((agf
= iocur_top
->data
) == NULL
) {
3945 dbprintf("can't read agf block for ag %u\n", agno
);
3951 if (INT_GET(agf
->agf_magicnum
, ARCH_CONVERT
) != XFS_AGF_MAGIC
) {
3953 dbprintf("bad agf magic # %#x in ag %u\n",
3954 INT_GET(agf
->agf_magicnum
, ARCH_CONVERT
), agno
);
3957 if (!XFS_AGF_GOOD_VERSION(INT_GET(agf
->agf_versionnum
, ARCH_CONVERT
))) {
3959 dbprintf("bad agf version # %#x in ag %u\n",
3960 INT_GET(agf
->agf_versionnum
, ARCH_CONVERT
), agno
);
3963 if (XFS_SB_BLOCK(mp
) != XFS_AGF_BLOCK(mp
))
3964 set_dbmap(agno
, XFS_AGF_BLOCK(mp
), 1, DBM_AGF
, agno
,
3966 if (sb
->sb_agblocks
> INT_GET(agf
->agf_length
, ARCH_CONVERT
))
3967 set_dbmap(agno
, INT_GET(agf
->agf_length
, ARCH_CONVERT
),
3968 sb
->sb_agblocks
- INT_GET(agf
->agf_length
, ARCH_CONVERT
),
3969 DBM_MISSING
, agno
, XFS_SB_BLOCK(mp
));
3971 set_cur(&typtab
[TYP_AGI
],
3972 XFS_AG_DADDR(mp
, agno
, XFS_AGI_DADDR(mp
)),
3973 XFS_FSS_TO_BB(mp
, 1), DB_RING_IGN
, NULL
);
3974 if ((agi
= iocur_top
->data
) == NULL
) {
3975 dbprintf("can't read agi block for ag %u\n", agno
);
3982 if (INT_GET(agi
->agi_magicnum
, ARCH_CONVERT
) != XFS_AGI_MAGIC
) {
3984 dbprintf("bad agi magic # %#x in ag %u\n",
3985 INT_GET(agi
->agi_magicnum
, ARCH_CONVERT
), agno
);
3988 if (!XFS_AGI_GOOD_VERSION(INT_GET(agi
->agi_versionnum
, ARCH_CONVERT
))) {
3990 dbprintf("bad agi version # %#x in ag %u\n",
3991 INT_GET(agi
->agi_versionnum
, ARCH_CONVERT
), agno
);
3994 if (XFS_SB_BLOCK(mp
) != XFS_AGI_BLOCK(mp
) &&
3995 XFS_AGF_BLOCK(mp
) != XFS_AGI_BLOCK(mp
))
3996 set_dbmap(agno
, XFS_AGI_BLOCK(mp
), 1, DBM_AGI
, agno
,
4001 INT_GET(agf
->agf_roots
[XFS_BTNUM_BNO
], ARCH_CONVERT
),
4002 INT_GET(agf
->agf_levels
[XFS_BTNUM_BNO
], ARCH_CONVERT
),
4003 1, scanfunc_bno
, TYP_BNOBT
);
4006 INT_GET(agf
->agf_roots
[XFS_BTNUM_CNT
], ARCH_CONVERT
),
4007 INT_GET(agf
->agf_levels
[XFS_BTNUM_CNT
], ARCH_CONVERT
),
4008 1, scanfunc_cnt
, TYP_CNTBT
);
4010 INT_GET(agi
->agi_root
, ARCH_CONVERT
),
4011 INT_GET(agi
->agi_level
, ARCH_CONVERT
),
4012 1, scanfunc_ino
, TYP_INOBT
);
4013 if (INT_GET(agf
->agf_freeblks
, ARCH_CONVERT
) != agffreeblks
) {
4015 dbprintf("agf_freeblks %u, counted %u in ag %u\n",
4016 INT_GET(agf
->agf_freeblks
, ARCH_CONVERT
),
4020 if (INT_GET(agf
->agf_longest
, ARCH_CONVERT
) != agflongest
) {
4022 dbprintf("agf_longest %u, counted %u in ag %u\n",
4023 INT_GET(agf
->agf_longest
, ARCH_CONVERT
),
4027 if (INT_GET(agi
->agi_count
, ARCH_CONVERT
) != agicount
) {
4029 dbprintf("agi_count %u, counted %u in ag %u\n",
4030 INT_GET(agi
->agi_count
, ARCH_CONVERT
),
4034 if (INT_GET(agi
->agi_freecount
, ARCH_CONVERT
) != agifreecount
) {
4036 dbprintf("agi_freecount %u, counted %u in ag %u\n",
4037 INT_GET(agi
->agi_freecount
, ARCH_CONVERT
),
4038 agifreecount
, agno
);
4041 for (i
= 0; i
< XFS_AGI_UNLINKED_BUCKETS
; i
++) {
4042 if (INT_GET(agi
->agi_unlinked
[i
], ARCH_CONVERT
) != NULLAGINO
) {
4044 xfs_agino_t agino
=INT_GET(agi
->agi_unlinked
[i
], ARCH_CONVERT
);
4045 dbprintf("agi unlinked bucket %d is %u in ag "
4046 "%u (inode=%lld)\n", i
, agino
, agno
,
4047 XFS_AGINO_TO_INO(mp
, agno
, agino
));
4061 xfs_agnumber_t seqno
= INT_GET(agf
->agf_seqno
, ARCH_CONVERT
);
4067 if (XFS_SB_BLOCK(mp
) != XFS_AGFL_BLOCK(mp
) &&
4068 XFS_AGF_BLOCK(mp
) != XFS_AGFL_BLOCK(mp
) &&
4069 XFS_AGI_BLOCK(mp
) != XFS_AGFL_BLOCK(mp
))
4070 set_dbmap(seqno
, XFS_AGFL_BLOCK(mp
), 1, DBM_AGFL
, seqno
,
4072 if (INT_GET(agf
->agf_flcount
, ARCH_CONVERT
) == 0)
4075 set_cur(&typtab
[TYP_AGFL
],
4076 XFS_AG_DADDR(mp
, seqno
, XFS_AGFL_DADDR(mp
)),
4077 XFS_FSS_TO_BB(mp
, 1), DB_RING_IGN
, NULL
);
4078 if ((agfl
= iocur_top
->data
) == NULL
) {
4079 dbprintf("can't read agfl block for ag %u\n", seqno
);
4083 i
= INT_GET(agf
->agf_flfirst
, ARCH_CONVERT
);
4086 bno
= INT_GET(agfl
->agfl_bno
[i
], ARCH_CONVERT
);
4087 set_dbmap(seqno
, bno
, 1, DBM_FREELIST
, seqno
,
4088 XFS_AGFL_BLOCK(mp
));
4090 if (i
== INT_GET(agf
->agf_fllast
, ARCH_CONVERT
))
4092 if (++i
== XFS_AGFL_SIZE(mp
))
4095 if (count
!= INT_GET(agf
->agf_flcount
, ARCH_CONVERT
)) {
4097 dbprintf("freeblk count %u != flcount %u in ag %u\n",
4098 count
, INT_GET(agf
->agf_flcount
, ARCH_CONVERT
),
4110 scan_lbtree_f_t func
,
4113 xfs_drfsbno_t
*totd
,
4114 xfs_drfsbno_t
*toti
,
4121 set_cur(&typtab
[btype
], XFS_FSB_TO_DADDR(mp
, root
), blkbb
, DB_RING_IGN
,
4123 if (iocur_top
->data
== NULL
) {
4125 dbprintf("can't read btree block %u/%u\n",
4126 XFS_FSB_TO_AGNO(mp
, root
),
4127 XFS_FSB_TO_AGBNO(mp
, root
));
4131 (*func
)(iocur_top
->data
, nlevels
- 1, type
, root
, id
, totd
, toti
, nex
,
4132 blkmapp
, isroot
, btype
);
4142 scan_sbtree_f_t func
,
4145 xfs_agnumber_t seqno
= INT_GET(agf
->agf_seqno
, ARCH_CONVERT
);
4148 set_cur(&typtab
[btype
],
4149 XFS_AGB_TO_DADDR(mp
, seqno
, root
), blkbb
, DB_RING_IGN
, NULL
);
4150 if (iocur_top
->data
== NULL
) {
4152 dbprintf("can't read btree block %u/%u\n", seqno
, root
);
4156 (*func
)(iocur_top
->data
, nlevels
- 1, agf
, root
, isroot
);
4162 xfs_btree_lblock_t
*ablock
,
4167 xfs_drfsbno_t
*totd
,
4168 xfs_drfsbno_t
*toti
,
4174 xfs_agblock_t agbno
;
4175 xfs_agnumber_t agno
;
4176 xfs_bmbt_block_t
*block
= (xfs_bmbt_block_t
*)ablock
;
4179 xfs_bmbt_rec_32_t
*rp
;
4181 agno
= XFS_FSB_TO_AGNO(mp
, bno
);
4182 agbno
= XFS_FSB_TO_AGBNO(mp
, bno
);
4183 if (INT_GET(block
->bb_magic
, ARCH_CONVERT
) != XFS_BMAP_MAGIC
) {
4184 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
4185 dbprintf("bad magic # %#x in inode %lld bmbt block "
4187 INT_GET(block
->bb_magic
, ARCH_CONVERT
), id
->ino
, agno
, agbno
);
4190 if (INT_GET(block
->bb_level
, ARCH_CONVERT
) != level
) {
4191 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
4192 dbprintf("expected level %d got %d in inode %lld bmbt "
4194 level
, INT_GET(block
->bb_level
, ARCH_CONVERT
), id
->ino
, agno
, agbno
);
4197 set_dbmap(agno
, agbno
, 1, type
, agno
, agbno
);
4198 set_inomap(agno
, agbno
, 1, id
);
4201 if (INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) > mp
->m_bmap_dmxr
[0] ||
4202 (isroot
== 0 && INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) < mp
->m_bmap_dmnr
[0])) {
4203 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
4204 dbprintf("bad btree nrecs (%u, min=%u, max=%u) "
4205 "in inode %lld bmap block %lld\n",
4206 INT_GET(block
->bb_numrecs
, ARCH_CONVERT
), mp
->m_bmap_dmnr
[0],
4207 mp
->m_bmap_dmxr
[0], id
->ino
,
4212 rp
= (xfs_bmbt_rec_32_t
*)
4213 XFS_BTREE_REC_ADDR(mp
->m_sb
.sb_blocksize
, xfs_bmbt
,
4214 block
, 1, mp
->m_bmap_dmxr
[0]);
4215 *nex
+= INT_GET(block
->bb_numrecs
, ARCH_CONVERT
);
4216 process_bmbt_reclist(rp
, INT_GET(block
->bb_numrecs
, ARCH_CONVERT
), type
, id
, totd
,
4220 if (INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) > mp
->m_bmap_dmxr
[1] ||
4221 (isroot
== 0 && INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) < mp
->m_bmap_dmnr
[1])) {
4222 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
4223 dbprintf("bad btree nrecs (%u, min=%u, max=%u) in "
4224 "inode %lld bmap block %lld\n",
4225 INT_GET(block
->bb_numrecs
, ARCH_CONVERT
), mp
->m_bmap_dmnr
[1],
4226 mp
->m_bmap_dmxr
[1], id
->ino
, (xfs_dfsbno_t
)bno
);
4230 pp
= XFS_BTREE_PTR_ADDR(mp
->m_sb
.sb_blocksize
, xfs_bmbt
, block
, 1,
4231 mp
->m_bmap_dmxr
[0]);
4232 for (i
= 0; i
< INT_GET(block
->bb_numrecs
, ARCH_CONVERT
); i
++)
4233 scan_lbtree(INT_GET(pp
[i
], ARCH_CONVERT
), level
, scanfunc_bmap
, type
, id
, totd
, toti
,
4234 nex
, blkmapp
, 0, btype
);
4239 xfs_btree_sblock_t
*ablock
,
4245 xfs_alloc_block_t
*block
= (xfs_alloc_block_t
*)ablock
;
4247 xfs_alloc_ptr_t
*pp
;
4248 xfs_alloc_rec_t
*rp
;
4249 xfs_agnumber_t seqno
= INT_GET(agf
->agf_seqno
, ARCH_CONVERT
);
4251 if (INT_GET(block
->bb_magic
, ARCH_CONVERT
) != XFS_ABTB_MAGIC
) {
4252 dbprintf("bad magic # %#x in btbno block %u/%u\n",
4253 INT_GET(block
->bb_magic
, ARCH_CONVERT
), seqno
, bno
);
4258 if (INT_GET(block
->bb_level
, ARCH_CONVERT
) != level
) {
4260 dbprintf("expected level %d got %d in btbno block "
4262 level
, INT_GET(block
->bb_level
, ARCH_CONVERT
), seqno
, bno
);
4265 set_dbmap(seqno
, bno
, 1, DBM_BTBNO
, seqno
, bno
);
4267 if (INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) > mp
->m_alloc_mxr
[0] ||
4268 (isroot
== 0 && INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) < mp
->m_alloc_mnr
[0])) {
4269 dbprintf("bad btree nrecs (%u, min=%u, max=%u) in "
4270 "btbno block %u/%u\n",
4271 INT_GET(block
->bb_numrecs
, ARCH_CONVERT
), mp
->m_alloc_mnr
[0],
4272 mp
->m_alloc_mxr
[0], seqno
, bno
);
4276 rp
= XFS_BTREE_REC_ADDR(mp
->m_sb
.sb_blocksize
, xfs_alloc
, block
,
4277 1, mp
->m_alloc_mxr
[0]);
4278 for (i
= 0; i
< INT_GET(block
->bb_numrecs
, ARCH_CONVERT
); i
++) {
4279 set_dbmap(seqno
, INT_GET(rp
[i
].ar_startblock
, ARCH_CONVERT
),
4280 INT_GET(rp
[i
].ar_blockcount
, ARCH_CONVERT
), DBM_FREE1
,
4285 if (INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) > mp
->m_alloc_mxr
[1] ||
4286 (isroot
== 0 && INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) < mp
->m_alloc_mnr
[1])) {
4287 dbprintf("bad btree nrecs (%u, min=%u, max=%u) in btbno block "
4289 INT_GET(block
->bb_numrecs
, ARCH_CONVERT
), mp
->m_alloc_mnr
[1],
4290 mp
->m_alloc_mxr
[1], seqno
, bno
);
4294 pp
= XFS_BTREE_PTR_ADDR(mp
->m_sb
.sb_blocksize
, xfs_alloc
, block
, 1,
4295 mp
->m_alloc_mxr
[1]);
4296 for (i
= 0; i
< INT_GET(block
->bb_numrecs
, ARCH_CONVERT
); i
++)
4297 scan_sbtree(agf
, INT_GET(pp
[i
], ARCH_CONVERT
), level
, 0, scanfunc_bno
, TYP_BNOBT
);
4302 xfs_btree_sblock_t
*ablock
,
4308 xfs_alloc_block_t
*block
= (xfs_alloc_block_t
*)ablock
;
4309 xfs_agnumber_t seqno
= INT_GET(agf
->agf_seqno
, ARCH_CONVERT
);
4311 xfs_alloc_ptr_t
*pp
;
4312 xfs_alloc_rec_t
*rp
;
4314 if (INT_GET(block
->bb_magic
, ARCH_CONVERT
) != XFS_ABTC_MAGIC
) {
4315 dbprintf("bad magic # %#x in btcnt block %u/%u\n",
4316 INT_GET(block
->bb_magic
, ARCH_CONVERT
), seqno
, bno
);
4321 if (INT_GET(block
->bb_level
, ARCH_CONVERT
) != level
) {
4323 dbprintf("expected level %d got %d in btcnt block "
4325 level
, INT_GET(block
->bb_level
, ARCH_CONVERT
), seqno
, bno
);
4328 set_dbmap(seqno
, bno
, 1, DBM_BTCNT
, seqno
, bno
);
4330 if (INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) > mp
->m_alloc_mxr
[0] ||
4331 (isroot
== 0 && INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) < mp
->m_alloc_mnr
[0])) {
4332 dbprintf("bad btree nrecs (%u, min=%u, max=%u) in "
4333 "btbno block %u/%u\n",
4334 INT_GET(block
->bb_numrecs
, ARCH_CONVERT
), mp
->m_alloc_mnr
[0],
4335 mp
->m_alloc_mxr
[0], seqno
, bno
);
4339 rp
= XFS_BTREE_REC_ADDR(mp
->m_sb
.sb_blocksize
, xfs_alloc
, block
,
4340 1, mp
->m_alloc_mxr
[0]);
4341 for (i
= 0; i
< INT_GET(block
->bb_numrecs
, ARCH_CONVERT
); i
++) {
4342 check_set_dbmap(seqno
, INT_GET(rp
[i
].ar_startblock
, ARCH_CONVERT
),
4343 INT_GET(rp
[i
].ar_blockcount
, ARCH_CONVERT
), DBM_FREE1
, DBM_FREE2
,
4345 fdblocks
+= INT_GET(rp
[i
].ar_blockcount
, ARCH_CONVERT
);
4346 agffreeblks
+= INT_GET(rp
[i
].ar_blockcount
, ARCH_CONVERT
);
4347 if (INT_GET(rp
[i
].ar_blockcount
, ARCH_CONVERT
) > agflongest
)
4348 agflongest
= INT_GET(rp
[i
].ar_blockcount
, ARCH_CONVERT
);
4352 if (INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) > mp
->m_alloc_mxr
[1] ||
4353 (isroot
== 0 && INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) < mp
->m_alloc_mnr
[1])) {
4354 dbprintf("bad btree nrecs (%u, min=%u, max=%u) in btbno block "
4356 INT_GET(block
->bb_numrecs
, ARCH_CONVERT
), mp
->m_alloc_mnr
[1],
4357 mp
->m_alloc_mxr
[1], seqno
, bno
);
4361 pp
= XFS_BTREE_PTR_ADDR(mp
->m_sb
.sb_blocksize
, xfs_alloc
, block
, 1,
4362 mp
->m_alloc_mxr
[1]);
4363 for (i
= 0; i
< INT_GET(block
->bb_numrecs
, ARCH_CONVERT
); i
++)
4364 scan_sbtree(agf
, INT_GET(pp
[i
], ARCH_CONVERT
), level
, 0, scanfunc_cnt
, TYP_CNTBT
);
4369 xfs_btree_sblock_t
*ablock
,
4376 xfs_inobt_block_t
*block
= (xfs_inobt_block_t
*)ablock
;
4377 xfs_agnumber_t seqno
= INT_GET(agf
->agf_seqno
, ARCH_CONVERT
);
4383 xfs_inobt_ptr_t
*pp
;
4384 xfs_inobt_rec_t
*rp
;
4386 if (INT_GET(block
->bb_magic
, ARCH_CONVERT
) != XFS_IBT_MAGIC
) {
4387 dbprintf("bad magic # %#x in inobt block %u/%u\n",
4388 INT_GET(block
->bb_magic
, ARCH_CONVERT
), seqno
, bno
);
4392 if (INT_GET(block
->bb_level
, ARCH_CONVERT
) != level
) {
4394 dbprintf("expected level %d got %d in inobt block "
4396 level
, INT_GET(block
->bb_level
, ARCH_CONVERT
), seqno
, bno
);
4399 set_dbmap(seqno
, bno
, 1, DBM_BTINO
, seqno
, bno
);
4401 if (INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) > mp
->m_inobt_mxr
[0] ||
4402 (isroot
== 0 && INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) < mp
->m_inobt_mnr
[0])) {
4403 dbprintf("bad btree nrecs (%u, min=%u, max=%u) in "
4404 "inobt block %u/%u\n",
4405 INT_GET(block
->bb_numrecs
, ARCH_CONVERT
), mp
->m_inobt_mnr
[0],
4406 mp
->m_inobt_mxr
[0], seqno
, bno
);
4410 rp
= XFS_BTREE_REC_ADDR(mp
->m_sb
.sb_blocksize
, xfs_inobt
, block
,
4411 1, mp
->m_inobt_mxr
[0]);
4412 for (i
= 0; i
< INT_GET(block
->bb_numrecs
, ARCH_CONVERT
); i
++) {
4413 agino
= INT_GET(rp
[i
].ir_startino
, ARCH_CONVERT
);
4414 off
= XFS_INO_TO_OFFSET(mp
, agino
);
4416 if ((sbversion
& XFS_SB_VERSION_ALIGNBIT
) &&
4417 mp
->m_sb
.sb_inoalignmt
&&
4418 (XFS_INO_TO_AGBNO(mp
, agino
) %
4419 mp
->m_sb
.sb_inoalignmt
))
4420 sbversion
&= ~XFS_SB_VERSION_ALIGNBIT
;
4421 set_dbmap(seqno
, XFS_AGINO_TO_AGBNO(mp
, agino
),
4422 (xfs_extlen_t
)MAX(1,
4423 XFS_INODES_PER_CHUNK
>>
4424 mp
->m_sb
.sb_inopblog
),
4425 DBM_INODE
, seqno
, bno
);
4427 icount
+= XFS_INODES_PER_CHUNK
;
4428 agicount
+= XFS_INODES_PER_CHUNK
;
4429 ifree
+= INT_GET(rp
[i
].ir_freecount
, ARCH_CONVERT
);
4430 agifreecount
+= INT_GET(rp
[i
].ir_freecount
, ARCH_CONVERT
);
4432 set_cur(&typtab
[TYP_INODE
],
4433 XFS_AGB_TO_DADDR(mp
, seqno
,
4434 XFS_AGINO_TO_AGBNO(mp
, agino
)),
4435 (int)XFS_FSB_TO_BB(mp
, XFS_IALLOC_BLOCKS(mp
)),
4437 if (iocur_top
->data
== NULL
) {
4439 dbprintf("can't read inode block "
4442 XFS_AGINO_TO_AGBNO(mp
, agino
));
4446 for (j
= 0, nfree
= 0; j
< XFS_INODES_PER_CHUNK
; j
++) {
4447 if ((isfree
= XFS_INOBT_IS_FREE_DISK(&rp
[i
], j
)))
4449 process_inode(agf
, agino
+ j
,
4450 (xfs_dinode_t
*)((char *)iocur_top
->data
+ ((off
+ j
) << mp
->m_sb
.sb_inodelog
)),
4453 if (nfree
!= INT_GET(rp
[i
].ir_freecount
, ARCH_CONVERT
)) {
4455 dbprintf("ir_freecount/free mismatch, "
4456 "inode chunk %u/%u, freecount "
4459 INT_GET(rp
[i
].ir_freecount
, ARCH_CONVERT
), nfree
);
4466 if (INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) > mp
->m_inobt_mxr
[1] ||
4467 (isroot
== 0 && INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) < mp
->m_inobt_mnr
[1])) {
4468 dbprintf("bad btree nrecs (%u, min=%u, max=%u) in inobt block "
4470 INT_GET(block
->bb_numrecs
, ARCH_CONVERT
), mp
->m_inobt_mnr
[1],
4471 mp
->m_inobt_mxr
[1], seqno
, bno
);
4475 pp
= XFS_BTREE_PTR_ADDR(mp
->m_sb
.sb_blocksize
, xfs_inobt
, block
, 1,
4476 mp
->m_inobt_mxr
[1]);
4477 for (i
= 0; i
< INT_GET(block
->bb_numrecs
, ARCH_CONVERT
); i
++)
4478 scan_sbtree(agf
, INT_GET(pp
[i
], ARCH_CONVERT
), level
, 0, scanfunc_ino
, TYP_INOBT
);
4483 xfs_agnumber_t agno
,
4484 xfs_agblock_t agbno
,
4487 xfs_agnumber_t c_agno
,
4488 xfs_agblock_t c_agbno
)
4490 check_set_dbmap(agno
, agbno
, len
, DBM_UNKNOWN
, type
, c_agno
, c_agbno
);
4495 xfs_agnumber_t agno
,
4496 xfs_agblock_t agbno
,
4504 if (!check_inomap(agno
, agbno
, len
, id
->ino
))
4506 mayprint
= verbose
| id
->ilist
| blist_size
;
4507 for (i
= 0, idp
= &inomap
[agno
][agbno
]; i
< len
; i
++, idp
++) {
4510 (verbose
|| id
->ilist
|| CHECK_BLISTA(agno
, agbno
+ i
)))
4511 dbprintf("setting inode to %lld for block %u/%u\n",
4512 id
->ino
, agno
, agbno
+ i
);
4522 check_set_rdbmap(bno
, len
, DBM_UNKNOWN
, type
);
4535 if (!check_rinomap(bno
, len
, id
->ino
))
4537 mayprint
= verbose
| id
->ilist
| blist_size
;
4538 for (i
= 0, idp
= &inomap
[mp
->m_sb
.sb_agcount
][bno
];
4542 if (mayprint
&& (verbose
|| id
->ilist
|| CHECK_BLIST(bno
+ i
)))
4543 dbprintf("setting inode to %lld for rtblock %llu\n",
4555 id
->link_set
= nlink
;
4557 id
->security
= security
;
4558 if (verbose
|| id
->ilist
)
4559 dbprintf("inode %lld nlink %u %s dir\n", id
->ino
, nlink
,
4560 isdir
? "is" : "not");