2 * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 #include <xfs/libxfs.h>
36 IS_USER_QUOTA
, IS_PROJECT_QUOTA
, IS_GROUP_QUOTA
,
40 DBM_UNKNOWN
, DBM_AGF
, DBM_AGFL
, DBM_AGI
,
41 DBM_ATTR
, DBM_BTBMAPA
, DBM_BTBMAPD
, DBM_BTBNO
,
42 DBM_BTCNT
, DBM_BTINO
, DBM_DATA
, DBM_DIR
,
43 DBM_FREE1
, DBM_FREE2
, DBM_FREELIST
, DBM_INODE
,
44 DBM_LOG
, DBM_MISSING
, DBM_QUOTA
, DBM_RTBITMAP
,
45 DBM_RTDATA
, DBM_RTFREE
, DBM_RTSUM
, DBM_SB
,
50 typedef struct inodata
{
58 struct inodata
*parent
;
61 #define MIN_INODATA_HASH_SIZE 256
62 #define MAX_INODATA_HASH_SIZE 65536
63 #define INODATA_AVG_HASH_LENGTH 8
65 typedef struct qinfo
{
71 #define QDATA_HASH_SIZE 256
72 typedef struct qdata
{
79 typedef struct blkent
{
80 xfs_fileoff_t startoff
;
82 xfs_fsblock_t blks
[1];
84 #define BLKENT_SIZE(n) \
85 (offsetof(blkent_t, blks) + (sizeof(xfs_fsblock_t) * (n)))
87 typedef struct blkmap
{
92 #define BLKMAP_SIZE(n) \
93 (offsetof(blkmap_t, ents) + (sizeof(blkent_t *) * (n)))
95 typedef struct freetab
{
98 xfs_dir2_data_off_t ents
[1];
100 #define FREETAB_SIZE(n) \
101 (offsetof(freetab_t, ents) + (sizeof(xfs_dir2_data_off_t) * (n)))
103 typedef struct dirhash
{
104 struct dirhash
*next
;
105 xfs_dir2_leaf_entry_t entry
;
108 #define DIR_HASH_SIZE 1024
109 #define DIR_HASH_FUNC(h,a) (((h) ^ (a)) % DIR_HASH_SIZE)
111 static xfs_extlen_t agffreeblks
;
112 static xfs_extlen_t agflongest
;
113 static xfs_agino_t agicount
;
114 static xfs_agino_t agifreecount
;
115 static xfs_fsblock_t
*blist
;
116 static int blist_size
;
117 static char **dbmap
; /* really dbm_t:8 */
118 static dirhash_t
**dirhash
;
120 static __uint64_t fdblocks
;
121 static __uint64_t frextents
;
122 static __uint64_t icount
;
123 static __uint64_t ifree
;
124 static inodata_t
***inodata
;
125 static int inodata_hash_size
;
126 static inodata_t
***inomap
;
130 static qdata_t
**qpdata
;
132 static qdata_t
**qudata
;
134 static qdata_t
**qgdata
;
136 static unsigned sbversion
;
137 static int sbver_err
;
138 static int serious_error
;
140 static xfs_suminfo_t
*sumcompute
;
141 static xfs_suminfo_t
*sumfile
;
142 static const char *typename
[] = {
172 #define CHECK_BLIST(b) (blist_size && check_blist(b))
173 #define CHECK_BLISTA(a,b) \
174 (blist_size && check_blist(XFS_AGB_TO_FSB(mp, a, b)))
176 typedef void (*scan_lbtree_f_t
)(xfs_btree_lblock_t
*block
,
188 typedef void (*scan_sbtree_f_t
)(xfs_btree_sblock_t
*block
,
194 static void add_blist(xfs_fsblock_t bno
);
195 static void add_ilist(xfs_ino_t ino
);
196 static void addlink_inode(inodata_t
*id
);
197 static void addname_inode(inodata_t
*id
, char *name
, int namelen
);
198 static void addparent_inode(inodata_t
*id
, xfs_ino_t parent
);
199 static void blkent_append(blkent_t
**entp
, xfs_fsblock_t b
,
201 static blkent_t
*blkent_new(xfs_fileoff_t o
, xfs_fsblock_t b
,
203 static void blkent_prepend(blkent_t
**entp
, xfs_fsblock_t b
,
205 static blkmap_t
*blkmap_alloc(xfs_extnum_t
);
206 static void blkmap_free(blkmap_t
*blkmap
);
207 static xfs_fsblock_t
blkmap_get(blkmap_t
*blkmap
, xfs_fileoff_t o
);
208 static int blkmap_getn(blkmap_t
*blkmap
, xfs_fileoff_t o
, int nb
,
210 static void blkmap_grow(blkmap_t
**blkmapp
, blkent_t
**entp
,
212 static xfs_fileoff_t
blkmap_next_off(blkmap_t
*blkmap
, xfs_fileoff_t o
,
214 static void blkmap_set_blk(blkmap_t
**blkmapp
, xfs_fileoff_t o
,
216 static void blkmap_set_ext(blkmap_t
**blkmapp
, xfs_fileoff_t o
,
217 xfs_fsblock_t b
, xfs_extlen_t c
);
218 static void blkmap_shrink(blkmap_t
*blkmap
, blkent_t
**entp
);
219 static int blockfree_f(int argc
, char **argv
);
220 static int blockget_f(int argc
, char **argv
);
221 static int blocktrash_f(int argc
, char **argv
);
222 static int blockuse_f(int argc
, char **argv
);
223 static int check_blist(xfs_fsblock_t bno
);
224 static void check_dbmap(xfs_agnumber_t agno
, xfs_agblock_t agbno
,
225 xfs_extlen_t len
, dbm_t type
);
226 static int check_inomap(xfs_agnumber_t agno
, xfs_agblock_t agbno
,
227 xfs_extlen_t len
, xfs_ino_t c_ino
);
228 static void check_linkcounts(xfs_agnumber_t agno
);
229 static int check_range(xfs_agnumber_t agno
, xfs_agblock_t agbno
,
231 static void check_rdbmap(xfs_drfsbno_t bno
, xfs_extlen_t len
,
233 static int check_rinomap(xfs_drfsbno_t bno
, xfs_extlen_t len
,
235 static void check_rootdir(void);
236 static int check_rrange(xfs_drfsbno_t bno
, xfs_extlen_t len
);
237 static void check_set_dbmap(xfs_agnumber_t agno
,
238 xfs_agblock_t agbno
, xfs_extlen_t len
,
239 dbm_t type1
, dbm_t type2
,
240 xfs_agnumber_t c_agno
,
241 xfs_agblock_t c_agbno
);
242 static void check_set_rdbmap(xfs_drfsbno_t bno
, xfs_extlen_t len
,
243 dbm_t type1
, dbm_t type2
);
244 static void check_summary(void);
245 static void checknot_dbmap(xfs_agnumber_t agno
, xfs_agblock_t agbno
,
246 xfs_extlen_t len
, int typemask
);
247 static void checknot_rdbmap(xfs_drfsbno_t bno
, xfs_extlen_t len
,
249 static void dir_hash_add(xfs_dahash_t hash
,
250 xfs_dir2_dataptr_t addr
);
251 static void dir_hash_check(inodata_t
*id
, int v
);
252 static void dir_hash_done(void);
253 static void dir_hash_init(void);
254 static int dir_hash_see(xfs_dahash_t hash
,
255 xfs_dir2_dataptr_t addr
);
256 static inodata_t
*find_inode(xfs_ino_t ino
, int add
);
257 static void free_inodata(xfs_agnumber_t agno
);
258 static int init(int argc
, char **argv
);
259 static char *inode_name(xfs_ino_t ino
, inodata_t
**ipp
);
260 static int ncheck_f(int argc
, char **argv
);
261 static char *prepend_path(char *oldpath
, char *parent
);
262 static xfs_ino_t
process_block_dir_v2(blkmap_t
*blkmap
, int *dot
,
263 int *dotdot
, inodata_t
*id
);
264 static void process_bmbt_reclist(xfs_bmbt_rec_32_t
*rp
, int numrecs
,
265 dbm_t type
, inodata_t
*id
,
268 static void process_btinode(inodata_t
*id
, xfs_dinode_t
*dip
,
269 dbm_t type
, xfs_drfsbno_t
*totd
,
270 xfs_drfsbno_t
*toti
, xfs_extnum_t
*nex
,
271 blkmap_t
**blkmapp
, int whichfork
);
272 static xfs_ino_t
process_data_dir_v2(int *dot
, int *dotdot
,
273 inodata_t
*id
, int v
,
275 freetab_t
**freetabp
);
276 static xfs_dir2_data_free_t
277 *process_data_dir_v2_freefind(xfs_dir2_data_t
*data
,
278 xfs_dir2_data_unused_t
*dup
);
279 static void process_dir(xfs_dinode_t
*dip
, blkmap_t
*blkmap
,
281 static int process_dir_v1(xfs_dinode_t
*dip
, blkmap_t
*blkmap
,
282 int *dot
, int *dotdot
, inodata_t
*id
,
284 static int process_dir_v2(xfs_dinode_t
*dip
, blkmap_t
*blkmap
,
285 int *dot
, int *dotdot
, inodata_t
*id
,
287 static void process_exinode(inodata_t
*id
, xfs_dinode_t
*dip
,
288 dbm_t type
, xfs_drfsbno_t
*totd
,
289 xfs_drfsbno_t
*toti
, xfs_extnum_t
*nex
,
290 blkmap_t
**blkmapp
, int whichfork
);
291 static void process_inode(xfs_agf_t
*agf
, xfs_agino_t agino
,
292 xfs_dinode_t
*dip
, int isfree
);
293 static void process_lclinode(inodata_t
*id
, xfs_dinode_t
*dip
,
294 dbm_t type
, xfs_drfsbno_t
*totd
,
295 xfs_drfsbno_t
*toti
, xfs_extnum_t
*nex
,
296 blkmap_t
**blkmapp
, int whichfork
);
297 static xfs_ino_t
process_leaf_dir_v1(blkmap_t
*blkmap
, int *dot
,
298 int *dotdot
, inodata_t
*id
);
299 static xfs_ino_t
process_leaf_dir_v1_int(int *dot
, int *dotdot
,
301 static xfs_ino_t
process_leaf_node_dir_v2(blkmap_t
*blkmap
, int *dot
,
302 int *dotdot
, inodata_t
*id
,
303 xfs_fsize_t dirsize
);
304 static void process_leaf_node_dir_v2_free(inodata_t
*id
, int v
,
307 static void process_leaf_node_dir_v2_int(inodata_t
*id
, int v
,
310 static xfs_ino_t
process_node_dir_v1(blkmap_t
*blkmap
, int *dot
,
311 int *dotdot
, inodata_t
*id
);
312 static void process_quota(qtype_t qtype
, inodata_t
*id
,
314 static void process_rtbitmap(blkmap_t
*blkmap
);
315 static void process_rtsummary(blkmap_t
*blkmap
);
316 static xfs_ino_t
process_sf_dir_v2(xfs_dinode_t
*dip
, int *dot
,
317 int *dotdot
, inodata_t
*id
);
318 static xfs_ino_t
process_shortform_dir_v1(xfs_dinode_t
*dip
, int *dot
,
319 int *dotdot
, inodata_t
*id
);
320 static void quota_add(xfs_dqid_t
*p
, xfs_dqid_t
*g
, xfs_dqid_t
*u
,
321 int dq
, xfs_qcnt_t bc
, xfs_qcnt_t ic
,
323 static void quota_add1(qdata_t
**qt
, xfs_dqid_t id
, int dq
,
324 xfs_qcnt_t bc
, xfs_qcnt_t ic
,
326 static void quota_check(char *s
, qdata_t
**qt
);
327 static void quota_init(void);
328 static void scan_ag(xfs_agnumber_t agno
);
329 static void scan_freelist(xfs_agf_t
*agf
);
330 static void scan_lbtree(xfs_fsblock_t root
, int nlevels
,
331 scan_lbtree_f_t func
, dbm_t type
,
332 inodata_t
*id
, xfs_drfsbno_t
*totd
,
333 xfs_drfsbno_t
*toti
, xfs_extnum_t
*nex
,
334 blkmap_t
**blkmapp
, int isroot
,
336 static void scan_sbtree(xfs_agf_t
*agf
, xfs_agblock_t root
,
337 int nlevels
, int isroot
,
338 scan_sbtree_f_t func
, typnm_t btype
);
339 static void scanfunc_bmap(xfs_btree_lblock_t
*ablock
, int level
,
340 dbm_t type
, xfs_fsblock_t bno
,
341 inodata_t
*id
, xfs_drfsbno_t
*totd
,
342 xfs_drfsbno_t
*toti
, xfs_extnum_t
*nex
,
343 blkmap_t
**blkmapp
, int isroot
,
345 static void scanfunc_bno(xfs_btree_sblock_t
*ablock
, int level
,
346 xfs_agf_t
*agf
, xfs_agblock_t bno
,
348 static void scanfunc_cnt(xfs_btree_sblock_t
*ablock
, int level
,
349 xfs_agf_t
*agf
, xfs_agblock_t bno
,
351 static void scanfunc_ino(xfs_btree_sblock_t
*ablock
, int level
,
352 xfs_agf_t
*agf
, xfs_agblock_t bno
,
354 static void set_dbmap(xfs_agnumber_t agno
, xfs_agblock_t agbno
,
355 xfs_extlen_t len
, dbm_t type
,
356 xfs_agnumber_t c_agno
, xfs_agblock_t c_agbno
);
357 static void set_inomap(xfs_agnumber_t agno
, xfs_agblock_t agbno
,
358 xfs_extlen_t len
, inodata_t
*id
);
359 static void set_rdbmap(xfs_drfsbno_t bno
, xfs_extlen_t len
,
361 static void set_rinomap(xfs_drfsbno_t bno
, xfs_extlen_t len
,
363 static void setlink_inode(inodata_t
*id
, nlink_t nlink
, int isdir
,
366 static const cmdinfo_t blockfree_cmd
=
367 { "blockfree", NULL
, blockfree_f
, 0, 0, 0,
368 NULL
, "free block usage information", NULL
};
369 static const cmdinfo_t blockget_cmd
=
370 { "blockget", "check", blockget_f
, 0, -1, 0,
371 "[-s|-v] [-n] [-t] [-b bno]... [-i ino] ...",
372 "get block usage and check consistency", NULL
};
373 static const cmdinfo_t blocktrash_cmd
=
374 { "blocktrash", NULL
, blocktrash_f
, 0, -1, 0,
375 "[-n count] [-x minlen] [-y maxlen] [-s seed] [-0123] [-t type] ...",
376 "trash randomly selected block(s)", NULL
};
377 static const cmdinfo_t blockuse_cmd
=
378 { "blockuse", NULL
, blockuse_f
, 0, 3, 0,
379 "[-n] [-c blockcount]",
380 "print usage for current block(s)", NULL
};
381 static const cmdinfo_t ncheck_cmd
=
382 { "ncheck", NULL
, ncheck_f
, 0, -1, 0,
384 "print inode-name pairs", NULL
};
392 blist
= xrealloc(blist
, blist_size
* sizeof(bno
));
393 blist
[blist_size
- 1] = bno
;
402 id
= find_inode(ino
, 1);
404 dbprintf("-i %lld bad inode number\n", ino
);
415 if (verbose
|| id
->ilist
)
416 dbprintf("inode %lld add link, now %u\n", id
->ino
,
426 if (!nflag
|| id
->name
)
428 id
->name
= xmalloc(namelen
+ 1);
429 memcpy(id
->name
, name
, namelen
);
430 id
->name
[namelen
] = '\0';
440 pid
= find_inode(parent
, 1);
442 if (verbose
|| id
->ilist
|| (pid
&& pid
->ilist
))
443 dbprintf("inode %lld parent %lld\n", id
->ino
, parent
);
456 *entp
= ent
= xrealloc(ent
, BLKENT_SIZE(c
+ ent
->nblks
));
457 for (i
= 0; i
< c
; i
++)
458 ent
->blks
[ent
->nblks
+ i
] = b
+ i
;
471 ent
= xmalloc(BLKENT_SIZE(c
));
474 for (i
= 0; i
< c
; i
++)
475 ent
->blks
[i
] = b
+ i
;
490 newent
= xmalloc(BLKENT_SIZE(oldent
->nblks
+ c
));
491 newent
->nblks
= oldent
->nblks
+ c
;
492 newent
->startoff
= oldent
->startoff
- c
;
493 for (i
= 0; i
< c
; i
++)
494 newent
->blks
[i
] = b
+ c
;
495 for (; i
< oldent
->nblks
+ c
; i
++)
496 newent
->blks
[i
] = oldent
->blks
[i
- c
];
509 blkmap
= xmalloc(BLKMAP_SIZE(nex
));
510 blkmap
->naents
= nex
;
522 for (i
= 0, entp
= blkmap
->ents
; i
< blkmap
->nents
; i
++, entp
++)
536 for (i
= 0, entp
= blkmap
->ents
; i
< blkmap
->nents
; i
++, entp
++) {
538 if (o
>= ent
->startoff
&& o
< ent
->startoff
+ ent
->nblks
)
539 return ent
->blks
[o
- ent
->startoff
];
558 for (i
= nex
= 0, bmp
= NULL
, entp
= blkmap
->ents
;
562 if (ent
->startoff
>= o
+ nb
)
564 if (ent
->startoff
+ ent
->nblks
<= o
)
566 for (ento
= ent
->startoff
;
567 ento
< ent
->startoff
+ ent
->nblks
&& ento
< o
+ nb
;
572 bmp
[nex
- 1].startoff
+ bmp
[nex
- 1].blockcount
==
574 bmp
[nex
- 1].startblock
+ bmp
[nex
- 1].blockcount
==
575 ent
->blks
[ento
- ent
->startoff
])
576 bmp
[nex
- 1].blockcount
++;
578 bmp
= realloc(bmp
, ++nex
* sizeof(*bmp
));
579 bmp
[nex
- 1].startoff
= ento
;
580 bmp
[nex
- 1].startblock
=
581 ent
->blks
[ento
- ent
->startoff
];
582 bmp
[nex
- 1].blockcount
= 1;
583 bmp
[nex
- 1].flag
= 0;
602 idx
= (int)(entp
- blkmap
->ents
);
603 if (blkmap
->naents
== blkmap
->nents
) {
604 blkmap
= xrealloc(blkmap
, BLKMAP_SIZE(blkmap
->nents
+ 1));
608 for (i
= blkmap
->nents
; i
> idx
; i
--)
609 blkmap
->ents
[i
] = blkmap
->ents
[i
- 1];
610 blkmap
->ents
[idx
] = newent
;
622 ent
= blkmap
->ents
[blkmap
->nents
- 1];
623 return ent
->startoff
+ ent
->nblks
;
637 if (o
== NULLFILEOFF
) {
639 ent
= blkmap
->ents
[0];
640 return ent
->startoff
;
642 entp
= &blkmap
->ents
[*t
];
644 if (o
< ent
->startoff
+ ent
->nblks
- 1)
647 if (entp
>= &blkmap
->ents
[blkmap
->nents
])
651 return ent
->startoff
;
666 for (entp
= blkmap
->ents
; entp
< &blkmap
->ents
[blkmap
->nents
]; entp
++) {
668 if (o
< ent
->startoff
- 1) {
669 ent
= blkent_new(o
, b
, 1);
670 blkmap_grow(blkmapp
, entp
, ent
);
673 if (o
== ent
->startoff
- 1) {
674 blkent_prepend(entp
, b
, 1);
677 if (o
>= ent
->startoff
&& o
< ent
->startoff
+ ent
->nblks
) {
678 ent
->blks
[o
- ent
->startoff
] = b
;
681 if (o
> ent
->startoff
+ ent
->nblks
)
683 blkent_append(entp
, b
, 1);
684 if (entp
== &blkmap
->ents
[blkmap
->nents
- 1])
688 if (ent
->startoff
+ ent
->nblks
< nextent
->startoff
)
690 blkent_append(entp
, nextent
->blks
[0], nextent
->nblks
);
691 blkmap_shrink(blkmap
, &entp
[1]);
694 ent
= blkent_new(o
, b
, 1);
695 blkmap_grow(blkmapp
, entp
, ent
);
711 if (!blkmap
->nents
) {
712 blkmap
->ents
[0] = blkent_new(o
, b
, c
);
716 entp
= &blkmap
->ents
[blkmap
->nents
- 1];
718 if (ent
->startoff
+ ent
->nblks
== o
) {
719 blkent_append(entp
, b
, c
);
722 if (ent
->startoff
+ ent
->nblks
< o
) {
723 ent
= blkent_new(o
, b
, c
);
724 blkmap_grow(blkmapp
, &blkmap
->ents
[blkmap
->nents
], ent
);
727 for (i
= 0; i
< c
; i
++)
728 blkmap_set_blk(blkmapp
, o
+ i
, b
+ i
);
740 idx
= (int)(entp
- blkmap
->ents
);
741 for (i
= idx
+ 1; i
< blkmap
->nents
; i
++)
742 blkmap
->ents
[i
] = blkmap
->ents
[i
- 1];
756 dbprintf("block usage information not allocated\n");
759 rt
= mp
->m_sb
.sb_rextents
!= 0;
760 for (c
= 0; c
< mp
->m_sb
.sb_agcount
; c
++) {
770 sumcompute
= sumfile
= NULL
;
782 * Check consistency of xfs filesystem contents.
794 dbprintf("already have block usage information\n");
797 if (!init(argc
, argv
))
799 oldprefix
= dbprefix
;
801 for (agno
= 0, sbyell
= 0; agno
< mp
->m_sb
.sb_agcount
; agno
++) {
803 if (sbver_err
> 4 && !sbyell
&& sbver_err
>= agno
) {
805 dbprintf("WARNING: this may be a newer XFS "
816 dbprefix
= oldprefix
;
821 * Check that there are no blocks either
822 * a) unaccounted for or
823 * b) bno-free but not cnt-free
825 if (!tflag
) { /* are we in test mode, faking out freespace? */
826 for (agno
= 0; agno
< mp
->m_sb
.sb_agcount
; agno
++)
827 checknot_dbmap(agno
, 0, mp
->m_sb
.sb_agblocks
,
828 (1 << DBM_UNKNOWN
) | (1 << DBM_FREE1
));
830 for (agno
= 0; agno
< mp
->m_sb
.sb_agcount
; agno
++)
831 check_linkcounts(agno
);
832 if (mp
->m_sb
.sb_rblocks
) {
834 (xfs_extlen_t
)(mp
->m_sb
.sb_rextents
*
835 mp
->m_sb
.sb_rextsize
),
839 if (mp
->m_sb
.sb_icount
!= icount
) {
841 dbprintf("sb_icount %lld, counted %lld\n",
842 mp
->m_sb
.sb_icount
, icount
);
845 if (mp
->m_sb
.sb_ifree
!= ifree
) {
847 dbprintf("sb_ifree %lld, counted %lld\n",
848 mp
->m_sb
.sb_ifree
, ifree
);
851 if (mp
->m_sb
.sb_fdblocks
!= fdblocks
) {
853 dbprintf("sb_fdblocks %lld, counted %lld\n",
854 mp
->m_sb
.sb_fdblocks
, fdblocks
);
857 if (mp
->m_sb
.sb_frextents
!= frextents
) {
859 dbprintf("sb_frextents %lld, counted %lld\n",
860 mp
->m_sb
.sb_frextents
, frextents
);
863 if ((sbversion
& XFS_SB_VERSION_ATTRBIT
) &&
864 !XFS_SB_VERSION_HASATTR(&mp
->m_sb
)) {
866 dbprintf("sb versionnum missing attr bit %x\n",
867 XFS_SB_VERSION_ATTRBIT
);
870 if ((sbversion
& XFS_SB_VERSION_NLINKBIT
) &&
871 !XFS_SB_VERSION_HASNLINK(&mp
->m_sb
)) {
873 dbprintf("sb versionnum missing nlink bit %x\n",
874 XFS_SB_VERSION_NLINKBIT
);
877 if ((sbversion
& XFS_SB_VERSION_QUOTABIT
) &&
878 !XFS_SB_VERSION_HASQUOTA(&mp
->m_sb
)) {
880 dbprintf("sb versionnum missing quota bit %x\n",
881 XFS_SB_VERSION_QUOTABIT
);
884 if (!(sbversion
& XFS_SB_VERSION_ALIGNBIT
) &&
885 XFS_SB_VERSION_HASALIGN(&mp
->m_sb
)) {
887 dbprintf("sb versionnum extra align bit %x\n",
888 XFS_SB_VERSION_ALIGNBIT
);
892 quota_check("user", qudata
);
894 quota_check("project", qpdata
);
896 quota_check("group", qgdata
);
897 if (sbver_err
> mp
->m_sb
.sb_agcount
/ 2)
898 dbprintf("WARNING: this may be a newer XFS filesystem.\n");
901 dbprefix
= oldprefix
;
905 typedef struct ltab
{
926 static char *modestr
[] = {
927 "zeroed", "set", "flipped", "randomized"
930 len
= (int)((random() % (ltabp
->max
- ltabp
->min
+ 1)) + ltabp
->min
);
931 offset
= (int)(random() % (int)(mp
->m_sb
.sb_blocksize
* NBBY
));
934 set_cur(&typtab
[DBM_UNKNOWN
],
935 XFS_AGB_TO_DADDR(mp
, agno
, agbno
), blkbb
, DB_RING_IGN
, NULL
);
936 if ((buf
= iocur_top
->data
) == NULL
) {
937 dbprintf("can't read block %u/%u for trashing\n", agno
, agbno
);
941 for (bitno
= 0; bitno
< len
; bitno
++) {
942 bit
= (offset
+ bitno
) % (mp
->m_sb
.sb_blocksize
* NBBY
);
954 newbit
= (buf
[byte
] & mask
) == 0;
957 newbit
= (int)random() & 1;
967 printf("blocktrash: %u/%u %s block %d bit%s starting %d:%d %s\n",
968 agno
, agbno
, typename
[type
], len
, len
== 1 ? "" : "s",
969 offset
/ NBBY
, offset
% NBBY
, modestr
[mode
]);
980 xfs_drfsbno_t blocks
;
999 dbprintf("must run blockget first\n");
1007 gettimeofday(&now
, NULL
);
1008 seed
= (unsigned int)(now
.tv_sec
^ now
.tv_usec
);
1011 goodmask
= (1 << DBM_AGF
) |
1015 (1 << DBM_BTBMAPA
) |
1016 (1 << DBM_BTBMAPD
) |
1023 (1 << DBM_RTBITMAP
) |
1026 while ((c
= getopt(argc
, argv
, "0123n:s:t:x:y:")) != EOF
) {
1041 count
= (int)strtol(optarg
, &p
, 0);
1042 if (*p
!= '\0' || count
<= 0) {
1043 dbprintf("bad blocktrash count %s\n", optarg
);
1048 seed
= (uint
)strtoul(optarg
, &p
, 0);
1052 for (i
= 0; typename
[i
]; i
++) {
1053 if (strcmp(typename
[i
], optarg
) == 0)
1056 if (!typename
[i
] || (((1 << i
) & goodmask
) == 0)) {
1057 dbprintf("bad blocktrash type %s\n", optarg
);
1063 min
= (int)strtol(optarg
, &p
, 0);
1064 if (*p
!= '\0' || min
<= 0 ||
1065 min
> mp
->m_sb
.sb_blocksize
* NBBY
) {
1066 dbprintf("bad blocktrash min %s\n", optarg
);
1071 max
= (int)strtol(optarg
, &p
, 0);
1072 if (*p
!= '\0' || max
<= 0 ||
1073 max
> mp
->m_sb
.sb_blocksize
* NBBY
) {
1074 dbprintf("bad blocktrash max %s\n", optarg
);
1079 dbprintf("bad option for blocktrash command\n");
1084 dbprintf("bad min/max for blocktrash command\n");
1089 lentab
= xmalloc(sizeof(ltab_t
));
1090 lentab
->min
= lentab
->max
= min
;
1092 for (i
= min
+ 1; i
<= max
; i
++) {
1093 if ((i
& (i
- 1)) == 0) {
1094 lentab
= xrealloc(lentab
,
1095 sizeof(ltab_t
) * (lentablen
+ 1));
1096 lentab
[lentablen
].min
= lentab
[lentablen
].max
= i
;
1099 lentab
[lentablen
- 1].max
= i
;
1101 for (blocks
= 0, agno
= 0; agno
< mp
->m_sb
.sb_agcount
; agno
++) {
1102 for (agbno
= 0, p
= dbmap
[agno
];
1103 agbno
< mp
->m_sb
.sb_agblocks
;
1105 if ((1 << *p
) & tmask
)
1110 dbprintf("blocktrash: no matching blocks\n");
1114 dbprintf("blocktrash: seed %u\n", seed
);
1116 for (i
= 0; i
< count
; i
++) {
1117 randb
= (xfs_drfsbno_t
)((((__int64_t
)random() << 32) |
1118 random()) % blocks
);
1119 for (bi
= 0, agno
= 0, done
= 0;
1120 !done
&& agno
< mp
->m_sb
.sb_agcount
;
1122 for (agbno
= 0, p
= dbmap
[agno
];
1123 agbno
< mp
->m_sb
.sb_agblocks
;
1125 if (!((1 << *p
) & tmask
))
1129 blocktrash_b(agno
, agbno
, (dbm_t
)*p
,
1130 &lentab
[random() % lentablen
], mode
);
1145 xfs_agblock_t agbno
;
1146 xfs_agnumber_t agno
;
1156 dbprintf("must run blockget first\n");
1162 fsb
= XFS_DADDR_TO_FSB(mp
, iocur_top
->off
>> BBSHIFT
);
1163 agno
= XFS_FSB_TO_AGNO(mp
, fsb
);
1164 end
= agbno
= XFS_FSB_TO_AGBNO(mp
, fsb
);
1165 while ((c
= getopt(argc
, argv
, "c:n")) != EOF
) {
1168 count
= (int)strtol(optarg
, &p
, 0);
1169 end
= agbno
+ count
- 1;
1170 if (*p
!= '\0' || count
<= 0 ||
1171 end
>= mp
->m_sb
.sb_agblocks
) {
1172 dbprintf("bad blockuse count %s\n", optarg
);
1178 dbprintf("must run blockget -n first\n");
1184 dbprintf("bad option for blockuse command\n");
1188 while (agbno
<= end
) {
1189 p
= &dbmap
[agno
][agbno
];
1190 i
= inomap
[agno
][agbno
];
1191 dbprintf("block %llu (%u/%u) type %s",
1192 (xfs_dfsbno_t
)XFS_AGB_TO_FSB(mp
, agno
, agbno
),
1193 agno
, agbno
, typename
[(dbm_t
)*p
]);
1195 dbprintf(" inode %lld", i
->ino
);
1196 if (shownames
&& (p
= inode_name(i
->ino
, NULL
))) {
1213 for (i
= 0; i
< blist_size
; i
++) {
1214 if (blist
[i
] == bno
)
1222 xfs_agnumber_t agno
,
1223 xfs_agblock_t agbno
,
1230 for (i
= 0, p
= &dbmap
[agno
][agbno
]; i
< len
; i
++, p
++) {
1231 if ((dbm_t
)*p
!= type
) {
1232 if (!sflag
|| CHECK_BLISTA(agno
, agbno
+ i
))
1233 dbprintf("block %u/%u expected type %s got "
1235 agno
, agbno
+ i
, typename
[type
],
1236 typename
[(dbm_t
)*p
]);
1245 add_command(&blockfree_cmd
);
1246 add_command(&blockget_cmd
);
1248 add_command(&blocktrash_cmd
);
1249 add_command(&blockuse_cmd
);
1250 add_command(&ncheck_cmd
);
1255 xfs_agnumber_t agno
,
1256 xfs_agblock_t agbno
,
1264 if (!check_range(agno
, agbno
, len
)) {
1265 dbprintf("blocks %u/%u..%u claimed by inode %lld\n",
1266 agno
, agbno
, agbno
+ len
- 1, c_ino
);
1269 for (i
= 0, rval
= 1, idp
= &inomap
[agno
][agbno
]; i
< len
; i
++, idp
++) {
1271 if (!sflag
|| (*idp
)->ilist
||
1272 CHECK_BLISTA(agno
, agbno
+ i
))
1273 dbprintf("block %u/%u claimed by inode %lld, "
1274 "previous inum %lld\n",
1275 agno
, agbno
+ i
, c_ino
, (*idp
)->ino
);
1285 xfs_agnumber_t agno
)
1293 for (idx
= 0; idx
< inodata_hash_size
; ht
++, idx
++) {
1296 if (ep
->link_set
!= ep
->link_add
|| ep
->link_set
== 0) {
1297 path
= inode_name(ep
->ino
, NULL
);
1298 if (!path
&& ep
->link_add
)
1299 path
= xstrdup("?");
1300 if (!sflag
|| ep
->ilist
) {
1302 dbprintf("link count mismatch "
1303 "for inode %lld (name "
1309 else if (ep
->link_set
)
1310 dbprintf("disconnected inode "
1312 ep
->ino
, ep
->link_set
);
1314 dbprintf("allocated inode %lld "
1315 "has 0 link count\n",
1321 } else if (verbose
|| ep
->ilist
) {
1322 path
= inode_name(ep
->ino
, NULL
);
1324 dbprintf("inode %lld name %s\n",
1337 xfs_agnumber_t agno
,
1338 xfs_agblock_t agbno
,
1342 xfs_agblock_t low
= 0;
1343 xfs_agblock_t high
= 0;
1344 int valid_range
= 0;
1347 if (agno
>= mp
->m_sb
.sb_agcount
||
1348 agbno
+ len
- 1 >= mp
->m_sb
.sb_agblocks
) {
1349 for (i
= 0; i
< len
; i
++) {
1350 cur
= !sflag
|| CHECK_BLISTA(agno
, agbno
+ i
) ? 1 : 0;
1351 if (cur
== 1 && prev
== 0) {
1352 low
= high
= agbno
+ i
;
1354 } else if (cur
== 0 && prev
== 0) {
1356 } else if (cur
== 0 && prev
== 1) {
1358 dbprintf("block %u/%u out of range\n",
1361 dbprintf("blocks %u/%u..%u "
1366 } else if (cur
== 1 && prev
== 1) {
1373 dbprintf("block %u/%u out of range\n",
1376 dbprintf("blocks %u/%u..%u "
1396 for (i
= 0, p
= &dbmap
[mp
->m_sb
.sb_agcount
][bno
]; i
< len
; i
++, p
++) {
1397 if ((dbm_t
)*p
!= type
) {
1398 if (!sflag
|| CHECK_BLIST(bno
+ i
))
1399 dbprintf("rtblock %llu expected type %s got "
1401 bno
+ i
, typename
[type
],
1402 typename
[(dbm_t
)*p
]);
1418 if (!check_rrange(bno
, len
)) {
1419 dbprintf("rtblocks %llu..%llu claimed by inode %lld\n",
1420 bno
, bno
+ len
- 1, c_ino
);
1423 for (i
= 0, rval
= 1, idp
= &inomap
[mp
->m_sb
.sb_agcount
][bno
];
1427 if (!sflag
|| (*idp
)->ilist
|| CHECK_BLIST(bno
+ i
))
1428 dbprintf("rtblock %llu claimed by inode %lld, "
1429 "previous inum %lld\n",
1430 bno
+ i
, c_ino
, (*idp
)->ino
);
1443 id
= find_inode(mp
->m_sb
.sb_rootino
, 0);
1446 dbprintf("root inode %lld is missing\n",
1447 mp
->m_sb
.sb_rootino
);
1449 } else if (!id
->isdir
) {
1450 if (!sflag
|| id
->ilist
)
1451 dbprintf("root inode %lld is not a directory\n",
1452 mp
->m_sb
.sb_rootino
);
1464 if (bno
+ len
- 1 >= mp
->m_sb
.sb_rblocks
) {
1465 for (i
= 0; i
< len
; i
++) {
1466 if (!sflag
|| CHECK_BLIST(bno
+ i
))
1467 dbprintf("rtblock %llu out of range\n",
1478 xfs_agnumber_t agno
,
1479 xfs_agblock_t agbno
,
1483 xfs_agnumber_t c_agno
,
1484 xfs_agblock_t c_agbno
)
1490 if (!check_range(agno
, agbno
, len
)) {
1491 dbprintf("blocks %u/%u..%u claimed by block %u/%u\n", agno
,
1492 agbno
, agbno
+ len
- 1, c_agno
, c_agbno
);
1495 check_dbmap(agno
, agbno
, len
, type1
);
1496 mayprint
= verbose
| blist_size
;
1497 for (i
= 0, p
= &dbmap
[agno
][agbno
]; i
< len
; i
++, p
++) {
1499 if (mayprint
&& (verbose
|| CHECK_BLISTA(agno
, agbno
+ i
)))
1500 dbprintf("setting block %u/%u to %s\n", agno
, agbno
+ i
,
1516 if (!check_rrange(bno
, len
))
1518 check_rdbmap(bno
, len
, type1
);
1519 mayprint
= verbose
| blist_size
;
1520 for (i
= 0, p
= &dbmap
[mp
->m_sb
.sb_agcount
][bno
]; i
< len
; i
++, p
++) {
1522 if (mayprint
&& (verbose
|| CHECK_BLIST(bno
+ i
)))
1523 dbprintf("setting rtblock %llu to %s\n",
1524 bno
+ i
, typename
[type2
]);
1538 for (log
= 0; log
< mp
->m_rsumlevels
; log
++) {
1540 bno
< mp
->m_sb
.sb_rbmblocks
;
1541 bno
++, csp
++, fsp
++) {
1544 dbprintf("rt summary mismatch, size %d "
1545 "block %llu, file: %d, "
1547 log
, bno
, *fsp
, *csp
);
1556 xfs_agnumber_t agno
,
1557 xfs_agblock_t agbno
,
1564 if (!check_range(agno
, agbno
, len
))
1566 for (i
= 0, p
= &dbmap
[agno
][agbno
]; i
< len
; i
++, p
++) {
1567 if ((1 << *p
) & typemask
) {
1568 if (!sflag
|| CHECK_BLISTA(agno
, agbno
+ i
))
1569 dbprintf("block %u/%u type %s not expected\n",
1570 agno
, agbno
+ i
, typename
[(dbm_t
)*p
]);
1585 if (!check_rrange(bno
, len
))
1587 for (i
= 0, p
= &dbmap
[mp
->m_sb
.sb_agcount
][bno
]; i
< len
; i
++, p
++) {
1588 if ((1 << *p
) & typemask
) {
1589 if (!sflag
|| CHECK_BLIST(bno
+ i
))
1590 dbprintf("rtblock %llu type %s not expected\n",
1591 bno
+ i
, typename
[(dbm_t
)*p
]);
1600 xfs_dir2_dataptr_t addr
)
1605 i
= DIR_HASH_FUNC(hash
, addr
);
1606 p
= malloc(sizeof(*p
));
1607 p
->next
= dirhash
[i
];
1609 p
->entry
.hashval
= hash
;
1610 p
->entry
.address
= addr
;
1622 for (i
= 0; i
< DIR_HASH_SIZE
; i
++) {
1623 for (p
= dirhash
[i
]; p
; p
= p
->next
) {
1626 if (!sflag
|| id
->ilist
|| v
)
1627 dbprintf("dir ino %lld missing leaf entry for "
1629 id
->ino
, p
->entry
.hashval
,
1643 for (i
= 0; i
< DIR_HASH_SIZE
; i
++) {
1644 for (p
= dirhash
[i
]; p
; p
= n
) {
1656 dirhash
= calloc(DIR_HASH_SIZE
, sizeof(*dirhash
));
1662 xfs_dir2_dataptr_t addr
)
1667 i
= DIR_HASH_FUNC(hash
, addr
);
1668 for (p
= dirhash
[i
]; p
; p
= p
->next
) {
1669 if (p
->entry
.hashval
== hash
&& p
->entry
.address
== addr
) {
1685 xfs_agnumber_t agno
;
1690 agno
= XFS_INO_TO_AGNO(mp
, ino
);
1691 agino
= XFS_INO_TO_AGINO(mp
, ino
);
1692 if (agno
>= mp
->m_sb
.sb_agcount
||
1693 XFS_AGINO_TO_INO(mp
, agno
, agino
) != ino
)
1695 htab
= inodata
[agno
];
1696 ih
= agino
% inodata_hash_size
;
1699 if (ent
->ino
== ino
)
1705 ent
= xcalloc(1, sizeof(*ent
));
1707 ent
->next
= htab
[ih
];
1714 xfs_agnumber_t agno
)
1722 for (i
= 0; i
< inodata_hash_size
; i
++) {
1745 if (mp
->m_sb
.sb_magicnum
!= XFS_SB_MAGIC
) {
1746 dbprintf("bad superblock magic number %x, giving up\n",
1747 mp
->m_sb
.sb_magicnum
);
1752 rt
= mp
->m_sb
.sb_rextents
!= 0;
1753 dbmap
= xmalloc((mp
->m_sb
.sb_agcount
+ rt
) * sizeof(*dbmap
));
1754 inomap
= xmalloc((mp
->m_sb
.sb_agcount
+ rt
) * sizeof(*inomap
));
1755 inodata
= xmalloc(mp
->m_sb
.sb_agcount
* sizeof(*inodata
));
1757 (int)MAX(MIN(mp
->m_sb
.sb_icount
/
1758 (INODATA_AVG_HASH_LENGTH
* mp
->m_sb
.sb_agcount
),
1759 MAX_INODATA_HASH_SIZE
),
1760 MIN_INODATA_HASH_SIZE
);
1761 for (c
= 0; c
< mp
->m_sb
.sb_agcount
; c
++) {
1762 dbmap
[c
] = xcalloc(mp
->m_sb
.sb_agblocks
, sizeof(**dbmap
));
1763 inomap
[c
] = xcalloc(mp
->m_sb
.sb_agblocks
, sizeof(**inomap
));
1764 inodata
[c
] = xcalloc(inodata_hash_size
, sizeof(**inodata
));
1767 dbmap
[c
] = xcalloc(mp
->m_sb
.sb_rblocks
, sizeof(**dbmap
));
1768 inomap
[c
] = xcalloc(mp
->m_sb
.sb_rblocks
, sizeof(**inomap
));
1769 sumfile
= xcalloc(mp
->m_rsumsize
, 1);
1770 sumcompute
= xcalloc(mp
->m_rsumsize
, 1);
1772 nflag
= sflag
= tflag
= verbose
= optind
= 0;
1773 while ((c
= getopt(argc
, argv
, "b:i:npstv")) != EOF
) {
1776 bno
= strtoll(optarg
, NULL
, 10);
1780 ino
= strtoll(optarg
, NULL
, 10);
1799 dbprintf("bad option for blockget command\n");
1803 error
= sbver_err
= serious_error
= 0;
1804 fdblocks
= frextents
= icount
= ifree
= 0;
1805 sbversion
= XFS_SB_VERSION_4
;
1806 if (mp
->m_sb
.sb_inoalignmt
)
1807 sbversion
|= XFS_SB_VERSION_ALIGNBIT
;
1808 if ((mp
->m_sb
.sb_uquotino
&& mp
->m_sb
.sb_uquotino
!= NULLFSINO
) ||
1809 (mp
->m_sb
.sb_gquotino
&& mp
->m_sb
.sb_gquotino
!= NULLFSINO
))
1810 sbversion
|= XFS_SB_VERSION_QUOTABIT
;
1824 id
= find_inode(ino
, 0);
1829 if (id
->name
== NULL
)
1831 path
= xstrdup(id
->name
);
1832 while (id
->parent
) {
1834 if (id
->name
== NULL
)
1836 npath
= prepend_path(path
, id
->name
);
1848 xfs_agnumber_t agno
;
1861 if (!inodata
|| !nflag
) {
1862 dbprintf("must run blockget -n first\n");
1865 security
= optind
= ilist_size
= 0;
1867 while ((c
= getopt(argc
, argv
, "i:s")) != EOF
) {
1870 ino
= strtoll(optarg
, NULL
, 10);
1871 ilist
= xrealloc(ilist
, (ilist_size
+ 1) *
1873 ilist
[ilist_size
++] = ino
;
1879 dbprintf("bad option -%c for ncheck command\n", c
);
1884 for (ilp
= ilist
; ilp
< &ilist
[ilist_size
]; ilp
++) {
1886 if ((p
= inode_name(ino
, &hp
))) {
1887 dbprintf("%11llu %s", ino
, p
);
1897 for (agno
= 0; agno
< mp
->m_sb
.sb_agcount
; agno
++) {
1899 for (i
= 0; i
< inodata_hash_size
; i
++) {
1901 for (hp
= ht
[i
]; hp
; hp
= hp
->next
) {
1902 ino
= XFS_AGINO_TO_INO(mp
, agno
, hp
->ino
);
1903 p
= inode_name(ino
, &id
);
1906 if (!security
|| id
->security
) {
1907 dbprintf("%11llu %s", ino
, p
);
1927 len
= (int)(strlen(oldpath
) + strlen(parent
) + 2);
1928 path
= xmalloc(len
);
1929 snprintf(path
, len
, "%s/%s", parent
, oldpath
);
1934 process_block_dir_v2(
1948 nex
= blkmap_getn(blkmap
, 0, mp
->m_dirblkfsbs
, &bmp
);
1949 v
= id
->ilist
|| verbose
;
1952 dbprintf("block 0 for directory inode %lld is "
1960 make_bbmap(&bbmap
, nex
, bmp
);
1961 set_cur(&typtab
[TYP_DIR
], XFS_FSB_TO_DADDR(mp
, bmp
->startblock
),
1962 mp
->m_dirblkfsbs
* blkbb
, DB_RING_IGN
, nex
> 1 ? &bbmap
: NULL
);
1963 for (x
= 0; !v
&& x
< nex
; x
++) {
1964 for (b
= bmp
[x
].startblock
;
1965 !v
&& b
< bmp
[x
].startblock
+ bmp
[x
].blockcount
;
1970 if (iocur_top
->data
== NULL
) {
1971 if (!sflag
|| id
->ilist
|| v
)
1972 dbprintf("can't read block 0 for directory inode "
1979 parent
= process_data_dir_v2(dot
, dotdot
, id
, v
, mp
->m_dirdatablk
,
1981 dir_hash_check(id
, v
);
1988 process_bmbt_reclist(
1989 xfs_bmbt_rec_32_t
*rp
,
1996 xfs_agblock_t agbno
;
1997 xfs_agnumber_t agno
;
2003 xfs_agblock_t iagbno
;
2004 xfs_agnumber_t iagno
;
2011 v
= verbose
|| id
->ilist
;
2012 iagno
= XFS_INO_TO_AGNO(mp
, id
->ino
);
2013 iagbno
= XFS_INO_TO_AGBNO(mp
, id
->ino
);
2014 for (i
= 0; i
< numrecs
; i
++, rp
++) {
2015 convert_extent((xfs_bmbt_rec_64_t
*)rp
, &o
, &s
, &c
, &f
);
2017 dbprintf("inode %lld extent [%lld,%lld,%lld,%d]\n",
2018 id
->ino
, o
, s
, c
, f
);
2019 if (!sflag
&& i
> 0 && op
+ cp
> o
)
2020 dbprintf("bmap rec out of order, inode %lld entry %d\n",
2024 if (type
== DBM_RTDATA
) {
2025 if (!sflag
&& s
>= mp
->m_sb
.sb_rblocks
) {
2026 dbprintf("inode %lld bad rt block number %lld, "
2031 } else if (!sflag
) {
2032 agno
= XFS_FSB_TO_AGNO(mp
, s
);
2033 agbno
= XFS_FSB_TO_AGBNO(mp
, s
);
2034 if (agno
>= mp
->m_sb
.sb_agcount
||
2035 agbno
>= mp
->m_sb
.sb_agblocks
) {
2036 dbprintf("inode %lld bad block number %lld "
2037 "[%d,%d], offset %lld\n",
2038 id
->ino
, s
, agno
, agbno
, o
);
2041 if (agbno
+ c
- 1 >= mp
->m_sb
.sb_agblocks
) {
2042 dbprintf("inode %lld bad block number %lld "
2043 "[%d,%d], offset %lld\n",
2044 id
->ino
, s
+ c
- 1, agno
,
2045 agbno
+ (xfs_agblock_t
)c
- 1, o
);
2049 if (blkmapp
&& *blkmapp
)
2050 blkmap_set_ext(blkmapp
, (xfs_fileoff_t
)o
,
2051 (xfs_fsblock_t
)s
, (xfs_extlen_t
)c
);
2052 if (type
== DBM_RTDATA
) {
2053 set_rdbmap((xfs_fsblock_t
)s
, (xfs_extlen_t
)c
,
2055 set_rinomap((xfs_fsblock_t
)s
, (xfs_extlen_t
)c
, id
);
2056 for (b
= (xfs_fsblock_t
)s
;
2057 blist_size
&& b
< s
+ c
;
2060 dbprintf("inode %lld block %lld at "
2062 id
->ino
, (xfs_dfsbno_t
)b
, o
);
2065 agno
= XFS_FSB_TO_AGNO(mp
, (xfs_fsblock_t
)s
);
2066 agbno
= XFS_FSB_TO_AGBNO(mp
, (xfs_fsblock_t
)s
);
2067 set_dbmap(agno
, agbno
, (xfs_extlen_t
)c
, type
, iagno
,
2069 set_inomap(agno
, agbno
, (xfs_extlen_t
)c
, id
);
2070 for (b
= (xfs_fsblock_t
)s
;
2071 blist_size
&& b
< s
+ c
;
2072 b
++, o
++, agbno
++) {
2074 dbprintf("inode %lld block %lld at "
2076 id
->ino
, (xfs_dfsbno_t
)b
, o
);
2088 xfs_drfsbno_t
*totd
,
2089 xfs_drfsbno_t
*toti
,
2094 xfs_bmdr_block_t
*dib
;
2097 xfs_bmbt_rec_32_t
*rp
;
2099 dib
= (xfs_bmdr_block_t
*)XFS_DFORK_PTR(dip
, whichfork
);
2100 if (INT_GET(dib
->bb_level
, ARCH_CONVERT
) >= XFS_BM_MAXLEVELS(mp
, whichfork
)) {
2101 if (!sflag
|| id
->ilist
)
2102 dbprintf("level for ino %lld %s fork bmap root too "
2105 whichfork
== XFS_DATA_FORK
? "data" : "attr",
2106 INT_GET(dib
->bb_level
, ARCH_CONVERT
));
2110 if (INT_GET(dib
->bb_numrecs
, ARCH_CONVERT
) >
2111 XFS_BTREE_BLOCK_MAXRECS(XFS_DFORK_SIZE_HOST(dip
, mp
, whichfork
),
2112 xfs_bmdr
, INT_GET(dib
->bb_level
, ARCH_CONVERT
) == 0)) {
2113 if (!sflag
|| id
->ilist
)
2114 dbprintf("numrecs for ino %lld %s fork bmap root too "
2117 whichfork
== XFS_DATA_FORK
? "data" : "attr",
2118 INT_GET(dib
->bb_numrecs
, ARCH_CONVERT
));
2122 if (INT_GET(dib
->bb_level
, ARCH_CONVERT
) == 0) {
2123 rp
= (xfs_bmbt_rec_32_t
*)XFS_BTREE_REC_ADDR(
2124 XFS_DFORK_SIZE_HOST(dip
, mp
, whichfork
),
2126 XFS_BTREE_BLOCK_MAXRECS(XFS_DFORK_SIZE(dip
, mp
,
2129 process_bmbt_reclist(rp
, INT_GET(dib
->bb_numrecs
, ARCH_CONVERT
), type
, id
, totd
,
2131 *nex
+= INT_GET(dib
->bb_numrecs
, ARCH_CONVERT
);
2134 pp
= XFS_BTREE_PTR_ADDR(XFS_DFORK_SIZE_HOST(dip
, mp
, whichfork
),
2136 XFS_BTREE_BLOCK_MAXRECS(XFS_DFORK_SIZE(dip
, mp
,
2139 for (i
= 0; i
< INT_GET(dib
->bb_numrecs
, ARCH_CONVERT
); i
++)
2140 scan_lbtree((xfs_fsblock_t
)INT_GET(pp
[i
], ARCH_CONVERT
), INT_GET(dib
->bb_level
, ARCH_CONVERT
),
2141 scanfunc_bmap
, type
, id
, totd
, toti
, nex
,
2143 whichfork
== XFS_DATA_FORK
?
2144 TYP_BMAPBTD
: TYP_BMAPBTA
);
2147 XFS_DFORK_SIZE_HOST(dip
, mp
, whichfork
) / sizeof(xfs_bmbt_rec_t
)) {
2148 if (!sflag
|| id
->ilist
)
2149 dbprintf("extent count for ino %lld %s fork too low "
2150 "(%d) for file format\n",
2152 whichfork
== XFS_DATA_FORK
? "data" : "attr",
2159 process_data_dir_v2(
2165 freetab_t
**freetabp
)
2167 xfs_dir2_dataptr_t addr
;
2168 xfs_dir2_data_free_t
*bf
;
2170 xfs_dir2_block_t
*block
;
2171 xfs_dir2_block_tail_t
*btp
= NULL
;
2174 xfs_dir2_data_t
*data
;
2176 xfs_dir2_data_entry_t
*dep
;
2177 xfs_dir2_data_free_t
*dfp
;
2178 xfs_dir2_data_unused_t
*dup
;
2186 xfs_dir2_leaf_entry_t
*lep
= NULL
;
2188 xfs_ino_t parent
= 0;
2192 xfs_dir2_data_off_t
*tagp
;
2194 data
= iocur_top
->data
;
2195 block
= iocur_top
->data
;
2196 if (INT_GET(block
->hdr
.magic
, ARCH_CONVERT
) != XFS_DIR2_BLOCK_MAGIC
&&
2197 INT_GET(data
->hdr
.magic
, ARCH_CONVERT
) != XFS_DIR2_DATA_MAGIC
) {
2199 dbprintf("bad directory data magic # %#x for dir ino "
2201 INT_GET(data
->hdr
.magic
, ARCH_CONVERT
), id
->ino
, dabno
);
2205 db
= XFS_DIR2_DA_TO_DB(mp
, dabno
);
2206 bf
= data
->hdr
.bestfree
;
2207 ptr
= (char *)data
->u
;
2208 if (INT_GET(block
->hdr
.magic
, ARCH_CONVERT
) == XFS_DIR2_BLOCK_MAGIC
) {
2209 btp
= XFS_DIR2_BLOCK_TAIL_P(mp
, block
);
2210 lep
= XFS_DIR2_BLOCK_LEAF_P(btp
);
2211 endptr
= (char *)lep
;
2212 if (endptr
<= ptr
|| endptr
> (char *)btp
) {
2213 endptr
= (char *)data
+ mp
->m_dirblksize
;
2216 dbprintf("bad block directory tail for dir ino "
2222 endptr
= (char *)data
+ mp
->m_dirblksize
;
2223 bf_err
= lastfree_err
= tag_err
= 0;
2224 count
= lastfree
= freeseen
= 0;
2225 if (INT_GET(bf
[0].length
, ARCH_CONVERT
) == 0) {
2226 bf_err
+= INT_GET(bf
[0].offset
, ARCH_CONVERT
) != 0;
2229 if (INT_GET(bf
[1].length
, ARCH_CONVERT
) == 0) {
2230 bf_err
+= INT_GET(bf
[1].offset
, ARCH_CONVERT
) != 0;
2233 if (INT_GET(bf
[2].length
, ARCH_CONVERT
) == 0) {
2234 bf_err
+= INT_GET(bf
[2].offset
, ARCH_CONVERT
) != 0;
2237 bf_err
+= INT_GET(bf
[0].length
, ARCH_CONVERT
) < INT_GET(bf
[1].length
, ARCH_CONVERT
);
2238 bf_err
+= INT_GET(bf
[1].length
, ARCH_CONVERT
) < INT_GET(bf
[2].length
, ARCH_CONVERT
);
2240 freetab
= *freetabp
;
2241 if (freetab
->naents
<= db
) {
2242 *freetabp
= freetab
=
2243 realloc(freetab
, FREETAB_SIZE(db
+ 1));
2244 for (i
= freetab
->naents
; i
< db
; i
++)
2245 freetab
->ents
[i
] = NULLDATAOFF
;
2246 freetab
->naents
= db
+ 1;
2248 if (freetab
->nents
< db
+ 1)
2249 freetab
->nents
= db
+ 1;
2250 freetab
->ents
[db
] = INT_GET(bf
[0].length
, ARCH_CONVERT
);
2252 while (ptr
< endptr
) {
2253 dup
= (xfs_dir2_data_unused_t
*)ptr
;
2254 if (INT_GET(dup
->freetag
, ARCH_CONVERT
) == XFS_DIR2_DATA_FREE_TAG
) {
2255 lastfree_err
+= lastfree
!= 0;
2256 if ((INT_GET(dup
->length
, ARCH_CONVERT
) & (XFS_DIR2_DATA_ALIGN
- 1)) ||
2257 INT_GET(dup
->length
, ARCH_CONVERT
) == 0 ||
2258 (char *)(tagp
= XFS_DIR2_DATA_UNUSED_TAG_P(dup
)) >=
2261 dbprintf("dir %lld block %d bad free "
2269 tag_err
+= INT_GET(*tagp
, ARCH_CONVERT
) != (char *)dup
- (char *)data
;
2270 dfp
= process_data_dir_v2_freefind(data
, dup
);
2272 i
= (int)(dfp
- bf
);
2273 bf_err
+= (freeseen
& (1 << i
)) != 0;
2276 bf_err
+= INT_GET(dup
->length
, ARCH_CONVERT
) > INT_GET(bf
[2].length
, ARCH_CONVERT
);
2277 ptr
+= INT_GET(dup
->length
, ARCH_CONVERT
);
2281 dep
= (xfs_dir2_data_entry_t
*)dup
;
2282 if (dep
->namelen
== 0) {
2284 dbprintf("dir %lld block %d zero length entry "
2287 (int)((char *)dep
- (char *)data
));
2290 tagp
= XFS_DIR2_DATA_ENTRY_TAG_P(dep
);
2291 if ((char *)tagp
>= endptr
) {
2293 dbprintf("dir %lld block %d bad entry at %d\n",
2295 (int)((char *)dep
- (char *)data
));
2299 tag_err
+= INT_GET(*tagp
, ARCH_CONVERT
) != (char *)dep
- (char *)data
;
2300 addr
= XFS_DIR2_DB_OFF_TO_DATAPTR(mp
, db
,
2301 (char *)dep
- (char *)data
);
2302 hash
= libxfs_da_hashname((char *)dep
->name
, dep
->namelen
);
2303 dir_hash_add(hash
, addr
);
2304 ptr
+= XFS_DIR2_DATA_ENTSIZE(dep
->namelen
);
2307 lino
= INT_GET(dep
->inumber
, ARCH_CONVERT
);
2308 cid
= find_inode(lino
, 1);
2310 dbprintf("dir %lld block %d entry %*.*s %lld\n",
2311 id
->ino
, dabno
, dep
->namelen
, dep
->namelen
,
2317 dbprintf("dir %lld block %d entry %*.*s bad "
2318 "inode number %lld\n",
2319 id
->ino
, dabno
, dep
->namelen
,
2320 dep
->namelen
, dep
->name
, lino
);
2323 if (dep
->namelen
== 2 && dep
->name
[0] == '.' &&
2324 dep
->name
[1] == '.') {
2327 dbprintf("multiple .. entries in dir "
2328 "%lld (%lld, %lld)\n",
2329 id
->ino
, parent
, lino
);
2332 parent
= cid
? lino
: NULLFSINO
;
2334 } else if (dep
->namelen
!= 1 || dep
->name
[0] != '.') {
2338 addname_inode(cid
, (char *)dep
->name
,
2342 if (lino
!= id
->ino
) {
2344 dbprintf("dir %lld entry . inode "
2345 "number mismatch (%lld)\n",
2352 if (INT_GET(data
->hdr
.magic
, ARCH_CONVERT
) == XFS_DIR2_BLOCK_MAGIC
) {
2353 endptr
= (char *)data
+ mp
->m_dirblksize
;
2354 for (i
= stale
= 0; lep
&& i
< INT_GET(btp
->count
, ARCH_CONVERT
); i
++) {
2355 if ((char *)&lep
[i
] >= endptr
) {
2357 dbprintf("dir %lld block %d bad count "
2359 id
->ino
, dabno
, INT_GET(btp
->count
, ARCH_CONVERT
));
2363 if (INT_GET(lep
[i
].address
, ARCH_CONVERT
) == XFS_DIR2_NULL_DATAPTR
)
2365 else if (dir_hash_see(INT_GET(lep
[i
].hashval
, ARCH_CONVERT
), INT_GET(lep
[i
].address
, ARCH_CONVERT
))) {
2367 dbprintf("dir %lld block %d extra leaf "
2369 id
->ino
, dabno
, INT_GET(lep
[i
].hashval
, ARCH_CONVERT
),
2370 INT_GET(lep
[i
].address
, ARCH_CONVERT
));
2375 bf_err
+= freeseen
!= 7;
2378 dbprintf("dir %lld block %d bad bestfree data\n",
2382 if (INT_GET(data
->hdr
.magic
, ARCH_CONVERT
) == XFS_DIR2_BLOCK_MAGIC
&&
2383 count
!= INT_GET(btp
->count
, ARCH_CONVERT
) - INT_GET(btp
->stale
, ARCH_CONVERT
)) {
2385 dbprintf("dir %lld block %d bad block tail count %d "
2387 id
->ino
, dabno
, INT_GET(btp
->count
, ARCH_CONVERT
), INT_GET(btp
->stale
, ARCH_CONVERT
));
2390 if (INT_GET(data
->hdr
.magic
, ARCH_CONVERT
) == XFS_DIR2_BLOCK_MAGIC
&& stale
!= INT_GET(btp
->stale
, ARCH_CONVERT
)) {
2392 dbprintf("dir %lld block %d bad stale tail count %d\n",
2393 id
->ino
, dabno
, INT_GET(btp
->stale
, ARCH_CONVERT
));
2398 dbprintf("dir %lld block %d consecutive free entries\n",
2404 dbprintf("dir %lld block %d entry/unused tag "
2412 static xfs_dir2_data_free_t
*
2413 process_data_dir_v2_freefind(
2414 xfs_dir2_data_t
*data
,
2415 xfs_dir2_data_unused_t
*dup
)
2417 xfs_dir2_data_free_t
*dfp
;
2418 xfs_dir2_data_aoff_t off
;
2420 off
= (xfs_dir2_data_aoff_t
)((char *)dup
- (char *)data
);
2421 if (INT_GET(dup
->length
, ARCH_CONVERT
) < INT_GET(data
->hdr
.bestfree
[XFS_DIR2_DATA_FD_COUNT
- 1].length
, ARCH_CONVERT
))
2423 for (dfp
= &data
->hdr
.bestfree
[0];
2424 dfp
< &data
->hdr
.bestfree
[XFS_DIR2_DATA_FD_COUNT
];
2426 if (INT_GET(dfp
->offset
, ARCH_CONVERT
) == 0)
2428 if (INT_GET(dfp
->offset
, ARCH_CONVERT
) == off
)
2446 if (XFS_DIR_IS_V2(mp
)) {
2447 if (process_dir_v2(dip
, blkmap
, &dot
, &dotdot
, id
, &parent
))
2451 if (process_dir_v1(dip
, blkmap
, &dot
, &dotdot
, id
, &parent
))
2454 bno
= XFS_INO_TO_FSB(mp
, id
->ino
);
2456 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2457 dbprintf("no . entry for directory %lld\n", id
->ino
);
2461 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2462 dbprintf("no .. entry for directory %lld\n", id
->ino
);
2464 } else if (parent
== id
->ino
&& id
->ino
!= mp
->m_sb
.sb_rootino
) {
2465 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2466 dbprintf(". and .. same for non-root directory %lld\n",
2469 } else if (id
->ino
== mp
->m_sb
.sb_rootino
&& id
->ino
!= parent
) {
2470 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2471 dbprintf("root directory %lld has .. %lld\n", id
->ino
,
2474 } else if (parent
!= NULLFSINO
&& id
->ino
!= parent
)
2475 addparent_inode(id
, parent
);
2487 if (dip
->di_core
.di_size
<= XFS_DFORK_DSIZE_HOST(dip
, mp
) &&
2488 dip
->di_core
.di_format
== XFS_DINODE_FMT_LOCAL
)
2490 process_shortform_dir_v1(dip
, dot
, dotdot
, id
);
2491 else if (dip
->di_core
.di_size
== XFS_LBSIZE(mp
) &&
2492 (dip
->di_core
.di_format
== XFS_DINODE_FMT_EXTENTS
||
2493 dip
->di_core
.di_format
== XFS_DINODE_FMT_BTREE
))
2494 *parent
= process_leaf_dir_v1(blkmap
, dot
, dotdot
, id
);
2495 else if (dip
->di_core
.di_size
>= XFS_LBSIZE(mp
) &&
2496 (dip
->di_core
.di_format
== XFS_DINODE_FMT_EXTENTS
||
2497 dip
->di_core
.di_format
== XFS_DINODE_FMT_BTREE
))
2498 *parent
= process_node_dir_v1(blkmap
, dot
, dotdot
, id
);
2500 dbprintf("bad size (%lld) or format (%d) for directory inode "
2502 dip
->di_core
.di_size
, (int)dip
->di_core
.di_format
,
2519 xfs_fileoff_t last
= 0;
2522 last
= blkmap_last_off(blkmap
);
2523 if (dip
->di_core
.di_size
<= XFS_DFORK_DSIZE_HOST(dip
, mp
) &&
2524 dip
->di_core
.di_format
== XFS_DINODE_FMT_LOCAL
)
2525 *parent
= process_sf_dir_v2(dip
, dot
, dotdot
, id
);
2526 else if (last
== mp
->m_dirblkfsbs
&&
2527 (dip
->di_core
.di_format
== XFS_DINODE_FMT_EXTENTS
||
2528 dip
->di_core
.di_format
== XFS_DINODE_FMT_BTREE
))
2529 *parent
= process_block_dir_v2(blkmap
, dot
, dotdot
, id
);
2530 else if (last
>= mp
->m_dirleafblk
+ mp
->m_dirblkfsbs
&&
2531 (dip
->di_core
.di_format
== XFS_DINODE_FMT_EXTENTS
||
2532 dip
->di_core
.di_format
== XFS_DINODE_FMT_BTREE
))
2533 *parent
= process_leaf_node_dir_v2(blkmap
, dot
, dotdot
, id
,
2534 dip
->di_core
.di_size
);
2536 dbprintf("bad size (%lld) or format (%d) for directory inode "
2538 dip
->di_core
.di_size
, (int)dip
->di_core
.di_format
,
2552 xfs_drfsbno_t
*totd
,
2553 xfs_drfsbno_t
*toti
,
2558 xfs_bmbt_rec_32_t
*rp
;
2560 rp
= (xfs_bmbt_rec_32_t
*)XFS_DFORK_PTR(dip
, whichfork
);
2561 *nex
= XFS_DFORK_NEXTENTS_HOST(dip
, whichfork
);
2564 XFS_DFORK_SIZE_HOST(dip
, mp
, whichfork
) / sizeof(xfs_bmbt_rec_32_t
)) {
2565 if (!sflag
|| id
->ilist
)
2566 dbprintf("bad number of extents %d for inode %lld\n",
2571 process_bmbt_reclist(rp
, *nex
, type
, id
, totd
, blkmapp
);
2582 xfs_fsblock_t bno
= 0;
2583 xfs_dinode_core_t tdic
;
2584 xfs_dinode_core_t
*dic
;
2585 inodata_t
*id
= NULL
;
2587 xfs_extnum_t nextents
= 0;
2590 xfs_drfsbno_t totblocks
;
2591 xfs_drfsbno_t totdblocks
= 0;
2592 xfs_drfsbno_t totiblocks
= 0;
2594 xfs_extnum_t anextents
= 0;
2595 xfs_drfsbno_t atotdblocks
= 0;
2596 xfs_drfsbno_t atotiblocks
= 0;
2601 static char okfmts
[] = {
2602 0, /* type 0 unused */
2603 1 << XFS_DINODE_FMT_DEV
, /* FIFO */
2604 1 << XFS_DINODE_FMT_DEV
, /* CHR */
2605 0, /* type 3 unused */
2606 (1 << XFS_DINODE_FMT_LOCAL
) |
2607 (1 << XFS_DINODE_FMT_EXTENTS
) |
2608 (1 << XFS_DINODE_FMT_BTREE
), /* DIR */
2609 0, /* type 5 unused */
2610 1 << XFS_DINODE_FMT_DEV
, /* BLK */
2611 0, /* type 7 unused */
2612 (1 << XFS_DINODE_FMT_EXTENTS
) |
2613 (1 << XFS_DINODE_FMT_BTREE
), /* REG */
2614 0, /* type 9 unused */
2615 (1 << XFS_DINODE_FMT_LOCAL
) |
2616 (1 << XFS_DINODE_FMT_EXTENTS
), /* LNK */
2617 0, /* type 11 unused */
2618 1 << XFS_DINODE_FMT_DEV
, /* SOCK */
2619 0, /* type 13 unused */
2620 1 << XFS_DINODE_FMT_UUID
, /* MNT */
2621 0 /* type 15 unused */
2623 static char *fmtnames
[] = {
2624 "dev", "local", "extents", "btree", "uuid"
2627 /* convert the core, then copy it back into the inode */
2628 libxfs_xlate_dinode_core((xfs_caddr_t
)&dip
->di_core
, &tdic
, 1);
2629 memcpy(&dip
->di_core
, &tdic
, sizeof(xfs_dinode_core_t
));
2632 ino
= XFS_AGINO_TO_INO(mp
, INT_GET(agf
->agf_seqno
, ARCH_CONVERT
), agino
);
2634 id
= find_inode(ino
, 1);
2635 bno
= XFS_INO_TO_FSB(mp
, ino
);
2638 if (dic
->di_magic
!= XFS_DINODE_MAGIC
) {
2639 if (!sflag
|| isfree
|| id
->ilist
|| CHECK_BLIST(bno
))
2640 dbprintf("bad magic number %#x for inode %lld\n",
2641 dic
->di_magic
, ino
);
2645 if (!XFS_DINODE_GOOD_VERSION(dic
->di_version
)) {
2646 if (!sflag
|| isfree
|| id
->ilist
|| CHECK_BLIST(bno
))
2647 dbprintf("bad version number %#x for inode %lld\n",
2648 dic
->di_version
, ino
);
2653 if (dic
->di_nblocks
!= 0) {
2654 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2655 dbprintf("bad nblocks %lld for free inode "
2657 dic
->di_nblocks
, ino
);
2660 if (dic
->di_version
== XFS_DINODE_VERSION_1
)
2661 nlink
= dic
->di_onlink
;
2663 nlink
= dic
->di_nlink
;
2665 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2666 dbprintf("bad nlink %d for free inode %lld\n",
2670 if (dic
->di_mode
!= 0) {
2671 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2672 dbprintf("bad mode %#o for free inode %lld\n",
2679 * di_mode is a 16-bit uint so no need to check the < 0 case
2681 if ((((dic
->di_mode
& S_IFMT
) >> 12) > 15) ||
2682 (!(okfmts
[(dic
->di_mode
& S_IFMT
) >> 12] & (1 << dic
->di_format
)))) {
2683 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2684 dbprintf("bad format %d for inode %lld type %#o\n",
2685 dic
->di_format
, id
->ino
, dic
->di_mode
& S_IFMT
);
2689 if ((unsigned int)XFS_DFORK_ASIZE_HOST(dip
, mp
) >= XFS_LITINO(mp
)) {
2690 if (!sflag
|| id
->ilist
)
2691 dbprintf("bad fork offset %d for inode %lld\n",
2692 dic
->di_forkoff
, id
->ino
);
2696 if ((unsigned int)dic
->di_aformat
> XFS_DINODE_FMT_BTREE
) {
2697 if (!sflag
|| id
->ilist
)
2698 dbprintf("bad attribute format %d for inode %lld\n",
2699 dic
->di_aformat
, id
->ino
);
2703 if (verbose
|| id
->ilist
|| CHECK_BLIST(bno
))
2704 dbprintf("inode %lld mode %#o fmt %s "
2706 "nex %d anex %d nblk %lld sz %lld%s%s%s%s%s%s%s\n",
2707 id
->ino
, dic
->di_mode
, fmtnames
[(int)dic
->di_format
],
2708 fmtnames
[(int)dic
->di_aformat
],
2711 dic
->di_nblocks
, dic
->di_size
,
2712 dic
->di_flags
& XFS_DIFLAG_REALTIME
? " rt" : "",
2713 dic
->di_flags
& XFS_DIFLAG_PREALLOC
? " pre" : "",
2714 dic
->di_flags
& XFS_DIFLAG_IMMUTABLE
? " imm" : "",
2715 dic
->di_flags
& XFS_DIFLAG_APPEND
? " app" : "",
2716 dic
->di_flags
& XFS_DIFLAG_SYNC
? " syn" : "",
2717 dic
->di_flags
& XFS_DIFLAG_NOATIME
? " noa" : "",
2718 dic
->di_flags
& XFS_DIFLAG_NODUMP
? " nod" : "");
2720 switch (dic
->di_mode
& S_IFMT
) {
2723 if (dic
->di_format
== XFS_DINODE_FMT_LOCAL
)
2725 blkmap
= blkmap_alloc(dic
->di_nextents
);
2728 if (dic
->di_flags
& XFS_DIFLAG_REALTIME
)
2730 else if (id
->ino
== mp
->m_sb
.sb_rbmino
) {
2731 type
= DBM_RTBITMAP
;
2732 blkmap
= blkmap_alloc(dic
->di_nextents
);
2734 } else if (id
->ino
== mp
->m_sb
.sb_rsumino
) {
2736 blkmap
= blkmap_alloc(dic
->di_nextents
);
2739 else if (id
->ino
== mp
->m_sb
.sb_uquotino
||
2740 id
->ino
== mp
->m_sb
.sb_gquotino
) {
2742 blkmap
= blkmap_alloc(dic
->di_nextents
);
2747 if (dic
->di_mode
& (S_ISUID
| S_ISGID
))
2758 if (dic
->di_version
== XFS_DINODE_VERSION_1
)
2759 setlink_inode(id
, dic
->di_onlink
, type
== DBM_DIR
, security
);
2761 sbversion
|= XFS_SB_VERSION_NLINKBIT
;
2762 setlink_inode(id
, dic
->di_nlink
, type
== DBM_DIR
, security
);
2764 switch (dic
->di_format
) {
2765 case XFS_DINODE_FMT_LOCAL
:
2766 process_lclinode(id
, dip
, type
, &totdblocks
, &totiblocks
,
2767 &nextents
, &blkmap
, XFS_DATA_FORK
);
2769 case XFS_DINODE_FMT_EXTENTS
:
2770 process_exinode(id
, dip
, type
, &totdblocks
, &totiblocks
,
2771 &nextents
, &blkmap
, XFS_DATA_FORK
);
2773 case XFS_DINODE_FMT_BTREE
:
2774 process_btinode(id
, dip
, type
, &totdblocks
, &totiblocks
,
2775 &nextents
, &blkmap
, XFS_DATA_FORK
);
2778 if (XFS_DFORK_Q(dip
)) {
2779 sbversion
|= XFS_SB_VERSION_ATTRBIT
;
2780 switch (dic
->di_aformat
) {
2781 case XFS_DINODE_FMT_LOCAL
:
2782 process_lclinode(id
, dip
, DBM_ATTR
, &atotdblocks
,
2783 &atotiblocks
, &anextents
, NULL
, XFS_ATTR_FORK
);
2785 case XFS_DINODE_FMT_EXTENTS
:
2786 process_exinode(id
, dip
, DBM_ATTR
, &atotdblocks
,
2787 &atotiblocks
, &anextents
, NULL
, XFS_ATTR_FORK
);
2789 case XFS_DINODE_FMT_BTREE
:
2790 process_btinode(id
, dip
, DBM_ATTR
, &atotdblocks
,
2791 &atotiblocks
, &anextents
, NULL
, XFS_ATTR_FORK
);
2795 if (qgdo
|| qpdo
|| qudo
) {
2803 bc
= totdblocks
+ totiblocks
+
2804 atotdblocks
+ atotiblocks
;
2808 bc
= totiblocks
+ atotdblocks
+ atotiblocks
;
2816 dqprid
= dic
->di_projid
; /* dquot ID is u32 */
2817 quota_add(&dqprid
, &dic
->di_gid
, &dic
->di_uid
,
2821 totblocks
= totdblocks
+ totiblocks
+ atotdblocks
+ atotiblocks
;
2822 if (totblocks
!= dic
->di_nblocks
) {
2823 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2824 dbprintf("bad nblocks %lld for inode %lld, counted "
2826 dic
->di_nblocks
, id
->ino
, totblocks
);
2829 if (nextents
!= dic
->di_nextents
) {
2830 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2831 dbprintf("bad nextents %d for inode %lld, counted %d\n",
2832 dic
->di_nextents
, id
->ino
, nextents
);
2835 if (anextents
!= dic
->di_anextents
) {
2836 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2837 dbprintf("bad anextents %d for inode %lld, counted "
2839 dic
->di_anextents
, id
->ino
, anextents
);
2842 if (type
== DBM_DIR
)
2843 process_dir(dip
, blkmap
, id
);
2844 else if (type
== DBM_RTBITMAP
)
2845 process_rtbitmap(blkmap
);
2846 else if (type
== DBM_RTSUM
)
2847 process_rtsummary(blkmap
);
2849 * If the CHKD flag is not set, this can legitimately contain garbage;
2850 * xfs_repair may have cleared that bit.
2852 else if (type
== DBM_QUOTA
) {
2853 if (id
->ino
== mp
->m_sb
.sb_uquotino
&&
2854 (mp
->m_sb
.sb_qflags
& XFS_UQUOTA_ACCT
) &&
2855 (mp
->m_sb
.sb_qflags
& XFS_UQUOTA_CHKD
))
2856 process_quota(IS_USER_QUOTA
, id
, blkmap
);
2857 else if (id
->ino
== mp
->m_sb
.sb_gquotino
&&
2858 (mp
->m_sb
.sb_qflags
& XFS_GQUOTA_ACCT
) &&
2859 (mp
->m_sb
.sb_qflags
& XFS_OQUOTA_CHKD
))
2860 process_quota(IS_GROUP_QUOTA
, id
, blkmap
);
2861 else if (id
->ino
== mp
->m_sb
.sb_gquotino
&&
2862 (mp
->m_sb
.sb_qflags
& XFS_PQUOTA_ACCT
) &&
2863 (mp
->m_sb
.sb_qflags
& XFS_OQUOTA_CHKD
))
2864 process_quota(IS_PROJECT_QUOTA
, id
, blkmap
);
2867 blkmap_free(blkmap
);
2876 xfs_drfsbno_t
*totd
,
2877 xfs_drfsbno_t
*toti
,
2882 xfs_attr_shortform_t
*asf
;
2884 xfs_dinode_core_t
*dic
;
2886 dic
= &dip
->di_core
;
2887 bno
= XFS_INO_TO_FSB(mp
, id
->ino
);
2888 if (whichfork
== XFS_DATA_FORK
&&
2889 dic
->di_size
> XFS_DFORK_DSIZE_HOST(dip
, mp
)) {
2890 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2891 dbprintf("local inode %lld data is too large (size "
2893 id
->ino
, dic
->di_size
);
2896 else if (whichfork
== XFS_ATTR_FORK
) {
2897 asf
= (xfs_attr_shortform_t
*)XFS_DFORK_PTR(dip
, whichfork
);
2898 if (INT_GET(asf
->hdr
.totsize
, ARCH_CONVERT
) > XFS_DFORK_ASIZE_HOST(dip
, mp
)) {
2899 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2900 dbprintf("local inode %lld attr is too large "
2902 id
->ino
, INT_GET(asf
->hdr
.totsize
, ARCH_CONVERT
));
2909 process_leaf_dir_v1(
2918 bno
= blkmap_get(blkmap
, 0);
2919 if (bno
== NULLFSBLOCK
) {
2920 if (!sflag
|| id
->ilist
)
2921 dbprintf("block 0 for directory inode %lld is "
2928 set_cur(&typtab
[TYP_DIR
], XFS_FSB_TO_DADDR(mp
, bno
), blkbb
, DB_RING_IGN
,
2930 if (iocur_top
->data
== NULL
) {
2931 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2932 dbprintf("can't read block 0 for directory inode "
2938 parent
= process_leaf_dir_v1_int(dot
, dotdot
, id
);
2944 process_leaf_dir_v1_int(
2951 xfs_dir_leaf_entry_t
*entry
;
2953 xfs_dir_leafblock_t
*leaf
;
2955 xfs_dir_leaf_name_t
*namest
;
2956 xfs_ino_t parent
= 0;
2959 bno
= XFS_DADDR_TO_FSB(mp
, iocur_top
->bb
);
2960 v
= verbose
|| id
->ilist
|| CHECK_BLIST(bno
);
2961 leaf
= iocur_top
->data
;
2962 if (INT_GET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
) != XFS_DIR_LEAF_MAGIC
) {
2963 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2964 dbprintf("bad directory leaf magic # %#x for dir ino "
2966 INT_GET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
), id
->ino
);
2970 entry
= &leaf
->entries
[0];
2971 for (i
= 0; i
< INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
); entry
++, i
++) {
2972 namest
= XFS_DIR_LEAF_NAMESTRUCT(leaf
, INT_GET(entry
->nameidx
, ARCH_CONVERT
));
2973 lino
= XFS_GET_DIR_INO8(namest
->inumber
);
2974 cid
= find_inode(lino
, 1);
2976 dbprintf("dir %lld entry %*.*s %lld\n", id
->ino
,
2977 entry
->namelen
, entry
->namelen
, namest
->name
,
2983 dbprintf("dir %lld entry %*.*s bad inode "
2985 id
->ino
, entry
->namelen
, entry
->namelen
,
2986 namest
->name
, lino
);
2989 if (entry
->namelen
== 2 && namest
->name
[0] == '.' &&
2990 namest
->name
[1] == '.') {
2992 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2993 dbprintf("multiple .. entries in dir "
2994 "%lld (%lld, %lld)\n",
2995 id
->ino
, parent
, lino
);
2998 parent
= cid
? lino
: NULLFSINO
;
3000 } else if (entry
->namelen
!= 1 || namest
->name
[0] != '.') {
3004 addname_inode(cid
, (char *)namest
->name
,
3008 if (lino
!= id
->ino
) {
3010 dbprintf("dir %lld entry . inode "
3011 "number mismatch (%lld)\n",
3022 process_leaf_node_dir_v2(
3027 xfs_fsize_t dirsize
)
3043 v2
= verbose
|| id
->ilist
;
3046 freetab
= malloc(FREETAB_SIZE(dirsize
/ mp
->m_dirblksize
));
3047 freetab
->naents
= (int)(dirsize
/ mp
->m_dirblksize
);
3049 for (i
= 0; i
< freetab
->naents
; i
++)
3050 freetab
->ents
[i
] = NULLDATAOFF
;
3052 while ((dbno
= blkmap_next_off(blkmap
, dbno
, &t
)) != NULLFILEOFF
) {
3053 nex
= blkmap_getn(blkmap
, dbno
, mp
->m_dirblkfsbs
, &bmp
);
3055 for (v
= v2
, x
= 0; !v
&& x
< nex
; x
++) {
3056 for (b
= bmp
[x
].startblock
;
3057 !v
&& b
< bmp
[x
].startblock
+ bmp
[x
].blockcount
;
3062 dbprintf("dir inode %lld block %u=%llu\n", id
->ino
,
3064 (xfs_dfsbno_t
)bmp
->startblock
);
3067 make_bbmap(&bbmap
, nex
, bmp
);
3068 set_cur(&typtab
[TYP_DIR
], XFS_FSB_TO_DADDR(mp
, bmp
->startblock
),
3069 mp
->m_dirblkfsbs
* blkbb
, DB_RING_IGN
,
3070 nex
> 1 ? &bbmap
: NULL
);
3072 if (iocur_top
->data
== NULL
) {
3074 dbprintf("can't read block %u for directory "
3076 (__uint32_t
)dbno
, id
->ino
);
3079 dbno
+= mp
->m_dirblkfsbs
- 1;
3082 if (dbno
< mp
->m_dirleafblk
) {
3083 lino
= process_data_dir_v2(dot
, dotdot
, id
, v
,
3084 (xfs_dablk_t
)dbno
, &freetab
);
3088 dbprintf("multiple .. entries "
3095 } else if (dbno
< mp
->m_dirfreeblk
) {
3096 process_leaf_node_dir_v2_int(id
, v
, (xfs_dablk_t
)dbno
,
3099 process_leaf_node_dir_v2_free(id
, v
, (xfs_dablk_t
)dbno
,
3103 dbno
+= mp
->m_dirblkfsbs
- 1;
3105 dir_hash_check(id
, v
);
3107 for (i
= 0; i
< freetab
->nents
; i
++) {
3108 if (freetab
->ents
[i
] != NULLDATAOFF
) {
3110 dbprintf("missing free index for data block %d "
3111 "in dir ino %lld\n",
3112 XFS_DIR2_DB_TO_DA(mp
, i
), id
->ino
);
3121 process_leaf_node_dir_v2_free(
3127 xfs_dir2_data_off_t ent
;
3128 xfs_dir2_free_t
*free
;
3133 free
= iocur_top
->data
;
3134 if (INT_GET(free
->hdr
.magic
, ARCH_CONVERT
) != XFS_DIR2_FREE_MAGIC
) {
3136 dbprintf("bad free block magic # %#x for dir ino %lld "
3138 INT_GET(free
->hdr
.magic
, ARCH_CONVERT
), id
->ino
, dabno
);
3142 maxent
= XFS_DIR2_MAX_FREE_BESTS(mp
);
3143 if (INT_GET(free
->hdr
.firstdb
, ARCH_CONVERT
) !=
3144 XFS_DIR2_DA_TO_DB(mp
, dabno
- mp
->m_dirfreeblk
) * maxent
) {
3146 dbprintf("bad free block firstdb %d for dir ino %lld "
3148 INT_GET(free
->hdr
.firstdb
, ARCH_CONVERT
), id
->ino
, dabno
);
3152 if (INT_GET(free
->hdr
.nvalid
, ARCH_CONVERT
) > maxent
|| INT_GET(free
->hdr
.nvalid
, ARCH_CONVERT
) < 0 ||
3153 INT_GET(free
->hdr
.nused
, ARCH_CONVERT
) > maxent
|| INT_GET(free
->hdr
.nused
, ARCH_CONVERT
) < 0 ||
3154 INT_GET(free
->hdr
.nused
, ARCH_CONVERT
) > INT_GET(free
->hdr
.nvalid
, ARCH_CONVERT
)) {
3156 dbprintf("bad free block nvalid/nused %d/%d for dir "
3157 "ino %lld block %d\n",
3158 INT_GET(free
->hdr
.nvalid
, ARCH_CONVERT
), INT_GET(free
->hdr
.nused
, ARCH_CONVERT
), id
->ino
,
3163 for (used
= i
= 0; i
< INT_GET(free
->hdr
.nvalid
, ARCH_CONVERT
); i
++) {
3164 if (freetab
->nents
<= INT_GET(free
->hdr
.firstdb
, ARCH_CONVERT
) + i
)
3167 ent
= freetab
->ents
[INT_GET(free
->hdr
.firstdb
, ARCH_CONVERT
) + i
];
3168 if (ent
!= INT_GET(free
->bests
[i
], ARCH_CONVERT
)) {
3170 dbprintf("bad free block ent %d is %d should "
3171 "be %d for dir ino %lld block %d\n",
3172 i
, INT_GET(free
->bests
[i
], ARCH_CONVERT
), ent
, id
->ino
, dabno
);
3175 if (INT_GET(free
->bests
[i
], ARCH_CONVERT
) != NULLDATAOFF
)
3177 if (ent
!= NULLDATAOFF
)
3178 freetab
->ents
[INT_GET(free
->hdr
.firstdb
, ARCH_CONVERT
) + i
] = NULLDATAOFF
;
3180 if (used
!= INT_GET(free
->hdr
.nused
, ARCH_CONVERT
)) {
3182 dbprintf("bad free block nused %d should be %d for dir "
3183 "ino %lld block %d\n",
3184 INT_GET(free
->hdr
.nused
, ARCH_CONVERT
), used
, id
->ino
, dabno
);
3190 process_leaf_node_dir_v2_int(
3197 xfs_dir2_data_off_t
*lbp
;
3198 xfs_dir2_leaf_t
*leaf
;
3199 xfs_dir2_leaf_entry_t
*lep
;
3200 xfs_dir2_leaf_tail_t
*ltp
;
3201 xfs_da_intnode_t
*node
;
3204 leaf
= iocur_top
->data
;
3205 switch (INT_GET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
)) {
3206 case XFS_DIR2_LEAF1_MAGIC
:
3207 if (INT_GET(leaf
->hdr
.info
.forw
, ARCH_CONVERT
) || INT_GET(leaf
->hdr
.info
.back
, ARCH_CONVERT
)) {
3209 dbprintf("bad leaf block forw/back pointers "
3210 "%d/%d for dir ino %lld block %d\n",
3211 INT_GET(leaf
->hdr
.info
.forw
, ARCH_CONVERT
),
3212 INT_GET(leaf
->hdr
.info
.back
, ARCH_CONVERT
), id
->ino
, dabno
);
3215 if (dabno
!= mp
->m_dirleafblk
) {
3217 dbprintf("single leaf block for dir ino %lld "
3218 "block %d should be at block %d\n",
3220 (xfs_dablk_t
)mp
->m_dirleafblk
);
3223 ltp
= XFS_DIR2_LEAF_TAIL_P(mp
, leaf
);
3224 lbp
= XFS_DIR2_LEAF_BESTS_P(ltp
);
3225 for (i
= 0; i
< INT_GET(ltp
->bestcount
, ARCH_CONVERT
); i
++) {
3226 if (freetab
->nents
<= i
|| freetab
->ents
[i
] != INT_GET(lbp
[i
], ARCH_CONVERT
)) {
3228 dbprintf("bestfree %d for dir ino %lld "
3229 "block %d doesn't match table "
3231 freetab
->nents
<= i
?
3235 XFS_DIR2_DB_TO_DA(mp
, i
),
3236 INT_GET(lbp
[i
], ARCH_CONVERT
));
3238 if (freetab
->nents
> i
)
3239 freetab
->ents
[i
] = NULLDATAOFF
;
3242 case XFS_DIR2_LEAFN_MAGIC
:
3243 /* if it's at the root location then we can check the
3244 * pointers are null XXX */
3246 case XFS_DA_NODE_MAGIC
:
3247 node
= iocur_top
->data
;
3248 if (INT_GET(node
->hdr
.level
, ARCH_CONVERT
) < 1 ||
3249 INT_GET(node
->hdr
.level
, ARCH_CONVERT
) > XFS_DA_NODE_MAXDEPTH
) {
3251 dbprintf("bad node block level %d for dir ino "
3253 INT_GET(node
->hdr
.level
, ARCH_CONVERT
), id
->ino
, dabno
);
3259 dbprintf("bad directory data magic # %#x for dir ino "
3261 INT_GET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
), id
->ino
, dabno
);
3266 for (i
= stale
= 0; i
< INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
); i
++) {
3267 if (INT_GET(lep
[i
].address
, ARCH_CONVERT
) == XFS_DIR2_NULL_DATAPTR
)
3269 else if (dir_hash_see(INT_GET(lep
[i
].hashval
, ARCH_CONVERT
), INT_GET(lep
[i
].address
, ARCH_CONVERT
))) {
3271 dbprintf("dir %lld block %d extra leaf entry "
3273 id
->ino
, dabno
, INT_GET(lep
[i
].hashval
, ARCH_CONVERT
),
3274 INT_GET(lep
[i
].address
, ARCH_CONVERT
));
3278 if (stale
!= INT_GET(leaf
->hdr
.stale
, ARCH_CONVERT
)) {
3280 dbprintf("dir %lld block %d stale mismatch "
3282 id
->ino
, dabno
, stale
,
3283 INT_GET(leaf
->hdr
.stale
, ARCH_CONVERT
));
3289 process_node_dir_v1(
3298 xfs_da_intnode_t
*node
;
3304 v
= verbose
|| id
->ilist
;
3307 while ((dbno
= blkmap_next_off(blkmap
, dbno
, &t
)) != NULLFILEOFF
) {
3308 bno
= blkmap_get(blkmap
, dbno
);
3309 v2
= bno
!= NULLFSBLOCK
&& CHECK_BLIST(bno
);
3310 if (bno
== NULLFSBLOCK
&& dbno
== 0) {
3312 dbprintf("can't read root block for directory "
3318 dbprintf("dir inode %lld block %u=%llu\n", id
->ino
,
3319 (__uint32_t
)dbno
, (xfs_dfsbno_t
)bno
);
3320 if (bno
== NULLFSBLOCK
)
3323 set_cur(&typtab
[TYP_DIR
], XFS_FSB_TO_DADDR(mp
, bno
), blkbb
,
3325 if ((node
= iocur_top
->data
) == NULL
) {
3326 if (!sflag
|| v
|| v2
)
3327 dbprintf("can't read block %u for directory "
3329 (__uint32_t
)dbno
, id
->ino
);
3334 if (INT_GET(node
->hdr
.info
.magic
, ARCH_CONVERT
) == XFS_DA_NODE_MAGIC
)
3336 if (INT_GET(node
->hdr
.info
.magic
, ARCH_CONVERT
) == XFS_DIR_NODE_MAGIC
)
3342 lino
= process_leaf_dir_v1_int(dot
, dotdot
, id
);
3345 if (!sflag
|| v
|| v2
)
3346 dbprintf("multiple .. entries in dir "
3368 u_int8_t exp_flags
= 0;
3379 exp_flags
= XFS_DQ_USER
;
3381 case IS_PROJECT_QUOTA
:
3383 exp_flags
= XFS_DQ_PROJ
;
3385 case IS_GROUP_QUOTA
:
3387 exp_flags
= XFS_DQ_GROUP
;
3393 perblock
= (uint
)(mp
->m_sb
.sb_blocksize
/ sizeof(*dqb
));
3396 while ((qbno
= blkmap_next_off(blkmap
, qbno
, &t
)) !=
3398 bno
= blkmap_get(blkmap
, qbno
);
3399 dqid
= (xfs_dqid_t
)qbno
* perblock
;
3400 cb
= CHECK_BLIST(bno
);
3401 scicb
= !sflag
|| id
->ilist
|| cb
;
3403 set_cur(&typtab
[TYP_DQBLK
], XFS_FSB_TO_DADDR(mp
, bno
), blkbb
,
3405 if ((dqb
= iocur_top
->data
) == NULL
) {
3408 dbprintf("can't read block %lld for %s quota "
3409 "inode (fsblock %lld)\n",
3410 (xfs_dfiloff_t
)qbno
, s
,
3415 for (i
= 0; i
< perblock
; i
++, dqid
++, dqb
++) {
3416 if (verbose
|| id
->ilist
|| cb
)
3417 dbprintf("%s dqblk %lld entry %d id %u bc "
3418 "%lld ic %lld rc %lld\n",
3419 s
, (xfs_dfiloff_t
)qbno
, i
, dqid
,
3420 INT_GET(dqb
->dd_diskdq
.d_bcount
, ARCH_CONVERT
),
3421 INT_GET(dqb
->dd_diskdq
.d_icount
, ARCH_CONVERT
),
3422 INT_GET(dqb
->dd_diskdq
.d_rtbcount
, ARCH_CONVERT
));
3423 if (INT_GET(dqb
->dd_diskdq
.d_magic
, ARCH_CONVERT
) != XFS_DQUOT_MAGIC
) {
3425 dbprintf("bad magic number %#x for %s "
3426 "dqblk %lld entry %d id %u\n",
3427 INT_GET(dqb
->dd_diskdq
.d_magic
, ARCH_CONVERT
), s
,
3428 (xfs_dfiloff_t
)qbno
, i
, dqid
);
3432 if (INT_GET(dqb
->dd_diskdq
.d_version
, ARCH_CONVERT
) != XFS_DQUOT_VERSION
) {
3434 dbprintf("bad version number %#x for "
3435 "%s dqblk %lld entry %d id "
3437 INT_GET(dqb
->dd_diskdq
.d_version
, ARCH_CONVERT
), s
,
3438 (xfs_dfiloff_t
)qbno
, i
, dqid
);
3442 if (INT_GET(dqb
->dd_diskdq
.d_flags
, ARCH_CONVERT
) != exp_flags
) {
3444 dbprintf("bad flags %#x for %s dqblk "
3445 "%lld entry %d id %u\n",
3446 INT_GET(dqb
->dd_diskdq
.d_flags
, ARCH_CONVERT
), s
,
3447 (xfs_dfiloff_t
)qbno
, i
, dqid
);
3451 if (INT_GET(dqb
->dd_diskdq
.d_id
, ARCH_CONVERT
) != dqid
) {
3453 dbprintf("bad id %u for %s dqblk %lld "
3455 INT_GET(dqb
->dd_diskdq
.d_id
, ARCH_CONVERT
), s
,
3456 (xfs_dfiloff_t
)qbno
, i
, dqid
);
3460 quota_add((qtype
== IS_PROJECT_QUOTA
) ? &dqid
: NULL
,
3461 (qtype
== IS_GROUP_QUOTA
) ? &dqid
: NULL
,
3462 (qtype
== IS_USER_QUOTA
) ? &dqid
: NULL
,
3464 INT_GET(dqb
->dd_diskdq
.d_bcount
, ARCH_CONVERT
),
3465 INT_GET(dqb
->dd_diskdq
.d_icount
, ARCH_CONVERT
),
3466 INT_GET(dqb
->dd_diskdq
.d_rtbcount
, ARCH_CONVERT
));
3476 #define xfs_highbit64 libxfs_highbit64 /* for XFS_RTBLOCKLOG macro */
3479 xfs_fileoff_t bmbno
;
3486 xfs_drfsbno_t rtbno
;
3490 xfs_rtword_t
*words
;
3492 bitsperblock
= mp
->m_sb
.sb_blocksize
* NBBY
;
3493 bit
= extno
= prevbit
= start_bmbno
= start_bit
= 0;
3494 bmbno
= NULLFILEOFF
;
3495 while ((bmbno
= blkmap_next_off(blkmap
, bmbno
, &t
)) !=
3497 bno
= blkmap_get(blkmap
, bmbno
);
3498 if (bno
== NULLFSBLOCK
) {
3500 dbprintf("block %lld for rtbitmap inode is "
3502 (xfs_dfiloff_t
)bmbno
);
3507 set_cur(&typtab
[TYP_RTBITMAP
], XFS_FSB_TO_DADDR(mp
, bno
), blkbb
,
3509 if ((words
= iocur_top
->data
) == NULL
) {
3512 dbprintf("can't read block %lld for rtbitmap "
3514 (xfs_dfiloff_t
)bmbno
);
3519 bit
< bitsperblock
&& extno
< mp
->m_sb
.sb_rextents
;
3521 if (xfs_isset(words
, bit
)) {
3522 rtbno
= extno
* mp
->m_sb
.sb_rextsize
;
3523 set_rdbmap(rtbno
, mp
->m_sb
.sb_rextsize
,
3527 start_bmbno
= (int)bmbno
;
3531 } else if (prevbit
== 1) {
3532 len
= ((int)bmbno
- start_bmbno
) *
3533 bitsperblock
+ (bit
- start_bit
);
3534 log
= XFS_RTBLOCKLOG(len
);
3535 offs
= XFS_SUMOFFS(mp
, log
, start_bmbno
);
3541 if (extno
== mp
->m_sb
.sb_rextents
)
3545 len
= ((int)bmbno
- start_bmbno
) * bitsperblock
+
3547 log
= XFS_RTBLOCKLOG(len
);
3548 offs
= XFS_SUMOFFS(mp
, log
, start_bmbno
);
3559 xfs_fileoff_t sumbno
;
3562 sumbno
= NULLFILEOFF
;
3563 while ((sumbno
= blkmap_next_off(blkmap
, sumbno
, &t
)) !=
3565 bno
= blkmap_get(blkmap
, sumbno
);
3566 if (bno
== NULLFSBLOCK
) {
3568 dbprintf("block %lld for rtsummary inode is "
3570 (xfs_dfiloff_t
)sumbno
);
3575 set_cur(&typtab
[TYP_RTSUMMARY
], XFS_FSB_TO_DADDR(mp
, bno
),
3576 blkbb
, DB_RING_IGN
, NULL
);
3577 if ((bytes
= iocur_top
->data
) == NULL
) {
3579 dbprintf("can't read block %lld for rtsummary "
3581 (xfs_dfiloff_t
)sumbno
);
3585 memcpy((char *)sumfile
+ sumbno
* mp
->m_sb
.sb_blocksize
, bytes
,
3586 mp
->m_sb
.sb_blocksize
);
3604 xfs_dir2_sf_entry_t
*sfe
;
3607 sf
= &dip
->di_u
.di_dir2sf
;
3609 v
= verbose
|| id
->ilist
;
3611 dbprintf("dir %lld entry . %lld\n", id
->ino
, id
->ino
);
3613 sfe
= XFS_DIR2_SF_FIRSTENTRY(sf
);
3614 offset
= XFS_DIR2_DATA_FIRST_OFFSET
;
3615 for (i
= INT_GET(sf
->hdr
.count
, ARCH_CONVERT
) - 1, i8
= 0; i
>= 0; i
--) {
3616 if ((__psint_t
)sfe
+ XFS_DIR2_SF_ENTSIZE_BYENTRY(sf
, sfe
) -
3617 (__psint_t
)sf
> dip
->di_core
.di_size
) {
3619 dbprintf("dir %llu bad size in entry at %d\n",
3621 (int)((char *)sfe
- (char *)sf
));
3625 lino
= XFS_DIR2_SF_GET_INUMBER(sf
, XFS_DIR2_SF_INUMBERP(sfe
));
3626 if (lino
> XFS_DIR2_MAX_SHORT_INUM
)
3628 cid
= find_inode(lino
, 1);
3631 dbprintf("dir %lld entry %*.*s bad inode "
3633 id
->ino
, sfe
->namelen
, sfe
->namelen
,
3640 addname_inode(cid
, (char *)sfe
->name
, sfe
->namelen
);
3643 dbprintf("dir %lld entry %*.*s offset %d %lld\n",
3644 id
->ino
, sfe
->namelen
, sfe
->namelen
, sfe
->name
,
3645 XFS_DIR2_SF_GET_OFFSET(sfe
), lino
);
3646 if (XFS_DIR2_SF_GET_OFFSET(sfe
) < offset
) {
3648 dbprintf("dir %lld entry %*.*s bad offset %d\n",
3649 id
->ino
, sfe
->namelen
, sfe
->namelen
,
3650 sfe
->name
, XFS_DIR2_SF_GET_OFFSET(sfe
));
3654 XFS_DIR2_SF_GET_OFFSET(sfe
) +
3655 XFS_DIR2_DATA_ENTSIZE(sfe
->namelen
);
3656 sfe
= XFS_DIR2_SF_NEXTENTRY(sf
, sfe
);
3658 if (i
< 0 && (__psint_t
)sfe
- (__psint_t
)sf
!= dip
->di_core
.di_size
) {
3660 dbprintf("dir %llu size is %lld, should be %u\n",
3661 id
->ino
, dip
->di_core
.di_size
,
3662 (uint
)((char *)sfe
- (char *)sf
));
3665 if (offset
+ (INT_GET(sf
->hdr
.count
, ARCH_CONVERT
) + 2) * sizeof(xfs_dir2_leaf_entry_t
) +
3666 sizeof(xfs_dir2_block_tail_t
) > mp
->m_dirblksize
) {
3668 dbprintf("dir %llu offsets too high\n", id
->ino
);
3671 lino
= XFS_DIR2_SF_GET_INUMBER(sf
, &sf
->hdr
.parent
);
3672 if (lino
> XFS_DIR2_MAX_SHORT_INUM
)
3674 cid
= find_inode(lino
, 1);
3679 dbprintf("dir %lld entry .. bad inode number %lld\n",
3684 dbprintf("dir %lld entry .. %lld\n", id
->ino
, lino
);
3685 if (i8
!= sf
->hdr
.i8count
) {
3687 dbprintf("dir %lld i8count mismatch is %d should be "
3689 id
->ino
, sf
->hdr
.i8count
, i8
);
3693 return cid
? lino
: NULLFSINO
;
3697 process_shortform_dir_v1(
3706 xfs_dir_shortform_t
*sf
;
3707 xfs_dir_sf_entry_t
*sfe
;
3710 sf
= &dip
->di_u
.di_dirsf
;
3712 v
= verbose
|| id
->ilist
;
3714 dbprintf("dir %lld entry . %lld\n", id
->ino
, id
->ino
);
3717 for (i
= INT_GET(sf
->hdr
.count
, ARCH_CONVERT
) - 1; i
>= 0; i
--) {
3718 lino
= XFS_GET_DIR_INO8(sfe
->inumber
);
3719 cid
= find_inode(lino
, 1);
3722 dbprintf("dir %lld entry %*.*s bad inode "
3724 id
->ino
, sfe
->namelen
, sfe
->namelen
,
3731 addname_inode(cid
, (char *)sfe
->name
, sfe
->namelen
);
3734 dbprintf("dir %lld entry %*.*s %lld\n", id
->ino
,
3735 sfe
->namelen
, sfe
->namelen
, sfe
->name
, lino
);
3736 sfe
= XFS_DIR_SF_NEXTENTRY(sfe
);
3738 if ((__psint_t
)sfe
- (__psint_t
)sf
!= dip
->di_core
.di_size
)
3739 dbprintf("dir %llu size is %lld, should be %d\n",
3740 id
->ino
, dip
->di_core
.di_size
,
3741 (int)((char *)sfe
- (char *)sf
));
3742 lino
= XFS_GET_DIR_INO8(sf
->hdr
.parent
);
3743 cid
= find_inode(lino
, 1);
3748 dbprintf("dir %lld entry .. bad inode number %lld\n",
3753 dbprintf("dir %lld entry .. %lld\n", id
->ino
, lino
);
3755 return cid
? lino
: NULLFSINO
;
3768 if (qudo
&& usrid
!= NULL
)
3769 quota_add1(qudata
, *usrid
, dq
, bc
, ic
, rc
);
3770 if (qgdo
&& grpid
!= NULL
)
3771 quota_add1(qgdata
, *grpid
, dq
, bc
, ic
, rc
);
3772 if (qpdo
&& prjid
!= NULL
)
3773 quota_add1(qpdata
, *prjid
, dq
, bc
, ic
, rc
);
3789 qh
= (int)(id
% QDATA_HASH_SIZE
);
3793 qi
= dq
? &qe
->dq
: &qe
->count
;
3801 qe
= xmalloc(sizeof(*qe
));
3803 qi
= dq
? &qe
->dq
: &qe
->count
;
3807 qi
= dq
? &qe
->count
: &qe
->dq
;
3808 qi
->bc
= qi
->ic
= qi
->rc
= 0;
3822 for (i
= 0; i
< QDATA_HASH_SIZE
; i
++) {
3826 if (qp
->count
.bc
!= qp
->dq
.bc
||
3827 qp
->count
.ic
!= qp
->dq
.ic
||
3828 qp
->count
.rc
!= qp
->dq
.rc
) {
3830 dbprintf("%s quota id %u, have/exp",
3832 if (qp
->count
.bc
!= qp
->dq
.bc
)
3833 dbprintf(" bc %lld/%lld",
3836 if (qp
->count
.ic
!= qp
->dq
.ic
)
3837 dbprintf(" ic %lld/%lld",
3840 if (qp
->count
.rc
!= qp
->dq
.rc
)
3841 dbprintf(" rc %lld/%lld",
3858 qudo
= mp
->m_sb
.sb_uquotino
!= 0 &&
3859 mp
->m_sb
.sb_uquotino
!= NULLFSINO
&&
3860 (mp
->m_sb
.sb_qflags
& XFS_UQUOTA_ACCT
) &&
3861 (mp
->m_sb
.sb_qflags
& XFS_UQUOTA_CHKD
);
3862 qgdo
= mp
->m_sb
.sb_gquotino
!= 0 &&
3863 mp
->m_sb
.sb_gquotino
!= NULLFSINO
&&
3864 (mp
->m_sb
.sb_qflags
& XFS_GQUOTA_ACCT
) &&
3865 (mp
->m_sb
.sb_qflags
& XFS_OQUOTA_CHKD
);
3866 qpdo
= mp
->m_sb
.sb_gquotino
!= 0 &&
3867 mp
->m_sb
.sb_gquotino
!= NULLFSINO
&&
3868 (mp
->m_sb
.sb_qflags
& XFS_PQUOTA_ACCT
) &&
3869 (mp
->m_sb
.sb_qflags
& XFS_OQUOTA_CHKD
);
3871 qudata
= xcalloc(QDATA_HASH_SIZE
, sizeof(qdata_t
*));
3873 qgdata
= xcalloc(QDATA_HASH_SIZE
, sizeof(qdata_t
*));
3875 qpdata
= xcalloc(QDATA_HASH_SIZE
, sizeof(qdata_t
*));
3880 xfs_agnumber_t agno
)
3888 agffreeblks
= agflongest
= 0;
3889 agicount
= agifreecount
= 0;
3891 set_cur(&typtab
[TYP_SB
],
3892 XFS_AG_DADDR(mp
, agno
, XFS_SB_DADDR
),
3893 XFS_FSS_TO_BB(mp
, 1), DB_RING_IGN
, NULL
);
3895 if (!iocur_top
->data
) {
3896 dbprintf("can't read superblock for ag %u\n", agno
);
3902 libxfs_xlate_sb(iocur_top
->data
, sb
, 1, XFS_SB_ALL_BITS
);
3904 if (sb
->sb_magicnum
!= XFS_SB_MAGIC
) {
3906 dbprintf("bad sb magic # %#x in ag %u\n",
3907 sb
->sb_magicnum
, agno
);
3910 if (!XFS_SB_GOOD_VERSION(sb
)) {
3912 dbprintf("bad sb version # %#x in ag %u\n",
3913 sb
->sb_versionnum
, agno
);
3917 if (agno
== 0 && sb
->sb_inprogress
!= 0) {
3919 dbprintf("mkfs not completed successfully\n");
3922 set_dbmap(agno
, XFS_SB_BLOCK(mp
), 1, DBM_SB
, agno
, XFS_SB_BLOCK(mp
));
3923 if (sb
->sb_logstart
&& XFS_FSB_TO_AGNO(mp
, sb
->sb_logstart
) == agno
)
3924 set_dbmap(agno
, XFS_FSB_TO_AGBNO(mp
, sb
->sb_logstart
),
3925 sb
->sb_logblocks
, DBM_LOG
, agno
, XFS_SB_BLOCK(mp
));
3927 set_cur(&typtab
[TYP_AGF
],
3928 XFS_AG_DADDR(mp
, agno
, XFS_AGF_DADDR(mp
)),
3929 XFS_FSS_TO_BB(mp
, 1), DB_RING_IGN
, NULL
);
3930 if ((agf
= iocur_top
->data
) == NULL
) {
3931 dbprintf("can't read agf block for ag %u\n", agno
);
3937 if (INT_GET(agf
->agf_magicnum
, ARCH_CONVERT
) != XFS_AGF_MAGIC
) {
3939 dbprintf("bad agf magic # %#x in ag %u\n",
3940 INT_GET(agf
->agf_magicnum
, ARCH_CONVERT
), agno
);
3943 if (!XFS_AGF_GOOD_VERSION(INT_GET(agf
->agf_versionnum
, ARCH_CONVERT
))) {
3945 dbprintf("bad agf version # %#x in ag %u\n",
3946 INT_GET(agf
->agf_versionnum
, ARCH_CONVERT
), agno
);
3949 if (XFS_SB_BLOCK(mp
) != XFS_AGF_BLOCK(mp
))
3950 set_dbmap(agno
, XFS_AGF_BLOCK(mp
), 1, DBM_AGF
, agno
,
3952 if (sb
->sb_agblocks
> INT_GET(agf
->agf_length
, ARCH_CONVERT
))
3953 set_dbmap(agno
, INT_GET(agf
->agf_length
, ARCH_CONVERT
),
3954 sb
->sb_agblocks
- INT_GET(agf
->agf_length
, ARCH_CONVERT
),
3955 DBM_MISSING
, agno
, XFS_SB_BLOCK(mp
));
3957 set_cur(&typtab
[TYP_AGI
],
3958 XFS_AG_DADDR(mp
, agno
, XFS_AGI_DADDR(mp
)),
3959 XFS_FSS_TO_BB(mp
, 1), DB_RING_IGN
, NULL
);
3960 if ((agi
= iocur_top
->data
) == NULL
) {
3961 dbprintf("can't read agi block for ag %u\n", agno
);
3968 if (INT_GET(agi
->agi_magicnum
, ARCH_CONVERT
) != XFS_AGI_MAGIC
) {
3970 dbprintf("bad agi magic # %#x in ag %u\n",
3971 INT_GET(agi
->agi_magicnum
, ARCH_CONVERT
), agno
);
3974 if (!XFS_AGI_GOOD_VERSION(INT_GET(agi
->agi_versionnum
, ARCH_CONVERT
))) {
3976 dbprintf("bad agi version # %#x in ag %u\n",
3977 INT_GET(agi
->agi_versionnum
, ARCH_CONVERT
), agno
);
3980 if (XFS_SB_BLOCK(mp
) != XFS_AGI_BLOCK(mp
) &&
3981 XFS_AGF_BLOCK(mp
) != XFS_AGI_BLOCK(mp
))
3982 set_dbmap(agno
, XFS_AGI_BLOCK(mp
), 1, DBM_AGI
, agno
,
3987 INT_GET(agf
->agf_roots
[XFS_BTNUM_BNO
], ARCH_CONVERT
),
3988 INT_GET(agf
->agf_levels
[XFS_BTNUM_BNO
], ARCH_CONVERT
),
3989 1, scanfunc_bno
, TYP_BNOBT
);
3992 INT_GET(agf
->agf_roots
[XFS_BTNUM_CNT
], ARCH_CONVERT
),
3993 INT_GET(agf
->agf_levels
[XFS_BTNUM_CNT
], ARCH_CONVERT
),
3994 1, scanfunc_cnt
, TYP_CNTBT
);
3996 INT_GET(agi
->agi_root
, ARCH_CONVERT
),
3997 INT_GET(agi
->agi_level
, ARCH_CONVERT
),
3998 1, scanfunc_ino
, TYP_INOBT
);
3999 if (INT_GET(agf
->agf_freeblks
, ARCH_CONVERT
) != agffreeblks
) {
4001 dbprintf("agf_freeblks %u, counted %u in ag %u\n",
4002 INT_GET(agf
->agf_freeblks
, ARCH_CONVERT
),
4006 if (INT_GET(agf
->agf_longest
, ARCH_CONVERT
) != agflongest
) {
4008 dbprintf("agf_longest %u, counted %u in ag %u\n",
4009 INT_GET(agf
->agf_longest
, ARCH_CONVERT
),
4013 if (INT_GET(agi
->agi_count
, ARCH_CONVERT
) != agicount
) {
4015 dbprintf("agi_count %u, counted %u in ag %u\n",
4016 INT_GET(agi
->agi_count
, ARCH_CONVERT
),
4020 if (INT_GET(agi
->agi_freecount
, ARCH_CONVERT
) != agifreecount
) {
4022 dbprintf("agi_freecount %u, counted %u in ag %u\n",
4023 INT_GET(agi
->agi_freecount
, ARCH_CONVERT
),
4024 agifreecount
, agno
);
4027 for (i
= 0; i
< XFS_AGI_UNLINKED_BUCKETS
; i
++) {
4028 if (INT_GET(agi
->agi_unlinked
[i
], ARCH_CONVERT
) != NULLAGINO
) {
4030 xfs_agino_t agino
=INT_GET(agi
->agi_unlinked
[i
], ARCH_CONVERT
);
4031 dbprintf("agi unlinked bucket %d is %u in ag "
4032 "%u (inode=%lld)\n", i
, agino
, agno
,
4033 XFS_AGINO_TO_INO(mp
, agno
, agino
));
4047 xfs_agnumber_t seqno
= INT_GET(agf
->agf_seqno
, ARCH_CONVERT
);
4053 if (XFS_SB_BLOCK(mp
) != XFS_AGFL_BLOCK(mp
) &&
4054 XFS_AGF_BLOCK(mp
) != XFS_AGFL_BLOCK(mp
) &&
4055 XFS_AGI_BLOCK(mp
) != XFS_AGFL_BLOCK(mp
))
4056 set_dbmap(seqno
, XFS_AGFL_BLOCK(mp
), 1, DBM_AGFL
, seqno
,
4058 if (INT_GET(agf
->agf_flcount
, ARCH_CONVERT
) == 0)
4061 set_cur(&typtab
[TYP_AGFL
],
4062 XFS_AG_DADDR(mp
, seqno
, XFS_AGFL_DADDR(mp
)),
4063 XFS_FSS_TO_BB(mp
, 1), DB_RING_IGN
, NULL
);
4064 if ((agfl
= iocur_top
->data
) == NULL
) {
4065 dbprintf("can't read agfl block for ag %u\n", seqno
);
4069 i
= INT_GET(agf
->agf_flfirst
, ARCH_CONVERT
);
4072 bno
= INT_GET(agfl
->agfl_bno
[i
], ARCH_CONVERT
);
4073 set_dbmap(seqno
, bno
, 1, DBM_FREELIST
, seqno
,
4074 XFS_AGFL_BLOCK(mp
));
4076 if (i
== INT_GET(agf
->agf_fllast
, ARCH_CONVERT
))
4078 if (++i
== XFS_AGFL_SIZE(mp
))
4081 if (count
!= INT_GET(agf
->agf_flcount
, ARCH_CONVERT
)) {
4083 dbprintf("freeblk count %u != flcount %u in ag %u\n",
4084 count
, INT_GET(agf
->agf_flcount
, ARCH_CONVERT
),
4096 scan_lbtree_f_t func
,
4099 xfs_drfsbno_t
*totd
,
4100 xfs_drfsbno_t
*toti
,
4107 set_cur(&typtab
[btype
], XFS_FSB_TO_DADDR(mp
, root
), blkbb
, DB_RING_IGN
,
4109 if (iocur_top
->data
== NULL
) {
4111 dbprintf("can't read btree block %u/%u\n",
4112 XFS_FSB_TO_AGNO(mp
, root
),
4113 XFS_FSB_TO_AGBNO(mp
, root
));
4117 (*func
)(iocur_top
->data
, nlevels
- 1, type
, root
, id
, totd
, toti
, nex
,
4118 blkmapp
, isroot
, btype
);
4128 scan_sbtree_f_t func
,
4131 xfs_agnumber_t seqno
= INT_GET(agf
->agf_seqno
, ARCH_CONVERT
);
4134 set_cur(&typtab
[btype
],
4135 XFS_AGB_TO_DADDR(mp
, seqno
, root
), blkbb
, DB_RING_IGN
, NULL
);
4136 if (iocur_top
->data
== NULL
) {
4138 dbprintf("can't read btree block %u/%u\n", seqno
, root
);
4142 (*func
)(iocur_top
->data
, nlevels
- 1, agf
, root
, isroot
);
4148 xfs_btree_lblock_t
*ablock
,
4153 xfs_drfsbno_t
*totd
,
4154 xfs_drfsbno_t
*toti
,
4160 xfs_agblock_t agbno
;
4161 xfs_agnumber_t agno
;
4162 xfs_bmbt_block_t
*block
= (xfs_bmbt_block_t
*)ablock
;
4165 xfs_bmbt_rec_32_t
*rp
;
4167 agno
= XFS_FSB_TO_AGNO(mp
, bno
);
4168 agbno
= XFS_FSB_TO_AGBNO(mp
, bno
);
4169 if (INT_GET(block
->bb_magic
, ARCH_CONVERT
) != XFS_BMAP_MAGIC
) {
4170 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
4171 dbprintf("bad magic # %#x in inode %lld bmbt block "
4173 INT_GET(block
->bb_magic
, ARCH_CONVERT
), id
->ino
, agno
, agbno
);
4176 if (INT_GET(block
->bb_level
, ARCH_CONVERT
) != level
) {
4177 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
4178 dbprintf("expected level %d got %d in inode %lld bmbt "
4180 level
, INT_GET(block
->bb_level
, ARCH_CONVERT
), id
->ino
, agno
, agbno
);
4183 set_dbmap(agno
, agbno
, 1, type
, agno
, agbno
);
4184 set_inomap(agno
, agbno
, 1, id
);
4187 if (INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) > mp
->m_bmap_dmxr
[0] ||
4188 (isroot
== 0 && INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) < mp
->m_bmap_dmnr
[0])) {
4189 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
4190 dbprintf("bad btree nrecs (%u, min=%u, max=%u) "
4191 "in inode %lld bmap block %lld\n",
4192 INT_GET(block
->bb_numrecs
, ARCH_CONVERT
), mp
->m_bmap_dmnr
[0],
4193 mp
->m_bmap_dmxr
[0], id
->ino
,
4198 rp
= (xfs_bmbt_rec_32_t
*)
4199 XFS_BTREE_REC_ADDR(mp
->m_sb
.sb_blocksize
, xfs_bmbt
,
4200 block
, 1, mp
->m_bmap_dmxr
[0]);
4201 *nex
+= INT_GET(block
->bb_numrecs
, ARCH_CONVERT
);
4202 process_bmbt_reclist(rp
, INT_GET(block
->bb_numrecs
, ARCH_CONVERT
), type
, id
, totd
,
4206 if (INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) > mp
->m_bmap_dmxr
[1] ||
4207 (isroot
== 0 && INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) < mp
->m_bmap_dmnr
[1])) {
4208 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
4209 dbprintf("bad btree nrecs (%u, min=%u, max=%u) in "
4210 "inode %lld bmap block %lld\n",
4211 INT_GET(block
->bb_numrecs
, ARCH_CONVERT
), mp
->m_bmap_dmnr
[1],
4212 mp
->m_bmap_dmxr
[1], id
->ino
, (xfs_dfsbno_t
)bno
);
4216 pp
= XFS_BTREE_PTR_ADDR(mp
->m_sb
.sb_blocksize
, xfs_bmbt
, block
, 1,
4217 mp
->m_bmap_dmxr
[0]);
4218 for (i
= 0; i
< INT_GET(block
->bb_numrecs
, ARCH_CONVERT
); i
++)
4219 scan_lbtree(INT_GET(pp
[i
], ARCH_CONVERT
), level
, scanfunc_bmap
, type
, id
, totd
, toti
,
4220 nex
, blkmapp
, 0, btype
);
4225 xfs_btree_sblock_t
*ablock
,
4231 xfs_alloc_block_t
*block
= (xfs_alloc_block_t
*)ablock
;
4233 xfs_alloc_ptr_t
*pp
;
4234 xfs_alloc_rec_t
*rp
;
4235 xfs_agnumber_t seqno
= INT_GET(agf
->agf_seqno
, ARCH_CONVERT
);
4237 if (INT_GET(block
->bb_magic
, ARCH_CONVERT
) != XFS_ABTB_MAGIC
) {
4238 dbprintf("bad magic # %#x in btbno block %u/%u\n",
4239 INT_GET(block
->bb_magic
, ARCH_CONVERT
), seqno
, bno
);
4244 if (INT_GET(block
->bb_level
, ARCH_CONVERT
) != level
) {
4246 dbprintf("expected level %d got %d in btbno block "
4248 level
, INT_GET(block
->bb_level
, ARCH_CONVERT
), seqno
, bno
);
4251 set_dbmap(seqno
, bno
, 1, DBM_BTBNO
, seqno
, bno
);
4253 if (INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) > mp
->m_alloc_mxr
[0] ||
4254 (isroot
== 0 && INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) < mp
->m_alloc_mnr
[0])) {
4255 dbprintf("bad btree nrecs (%u, min=%u, max=%u) in "
4256 "btbno block %u/%u\n",
4257 INT_GET(block
->bb_numrecs
, ARCH_CONVERT
), mp
->m_alloc_mnr
[0],
4258 mp
->m_alloc_mxr
[0], seqno
, bno
);
4262 rp
= XFS_BTREE_REC_ADDR(mp
->m_sb
.sb_blocksize
, xfs_alloc
, block
,
4263 1, mp
->m_alloc_mxr
[0]);
4264 for (i
= 0; i
< INT_GET(block
->bb_numrecs
, ARCH_CONVERT
); i
++) {
4265 set_dbmap(seqno
, INT_GET(rp
[i
].ar_startblock
, ARCH_CONVERT
),
4266 INT_GET(rp
[i
].ar_blockcount
, ARCH_CONVERT
), DBM_FREE1
,
4271 if (INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) > mp
->m_alloc_mxr
[1] ||
4272 (isroot
== 0 && INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) < mp
->m_alloc_mnr
[1])) {
4273 dbprintf("bad btree nrecs (%u, min=%u, max=%u) in btbno block "
4275 INT_GET(block
->bb_numrecs
, ARCH_CONVERT
), mp
->m_alloc_mnr
[1],
4276 mp
->m_alloc_mxr
[1], seqno
, bno
);
4280 pp
= XFS_BTREE_PTR_ADDR(mp
->m_sb
.sb_blocksize
, xfs_alloc
, block
, 1,
4281 mp
->m_alloc_mxr
[1]);
4282 for (i
= 0; i
< INT_GET(block
->bb_numrecs
, ARCH_CONVERT
); i
++)
4283 scan_sbtree(agf
, INT_GET(pp
[i
], ARCH_CONVERT
), level
, 0, scanfunc_bno
, TYP_BNOBT
);
4288 xfs_btree_sblock_t
*ablock
,
4294 xfs_alloc_block_t
*block
= (xfs_alloc_block_t
*)ablock
;
4295 xfs_agnumber_t seqno
= INT_GET(agf
->agf_seqno
, ARCH_CONVERT
);
4297 xfs_alloc_ptr_t
*pp
;
4298 xfs_alloc_rec_t
*rp
;
4300 if (INT_GET(block
->bb_magic
, ARCH_CONVERT
) != XFS_ABTC_MAGIC
) {
4301 dbprintf("bad magic # %#x in btcnt block %u/%u\n",
4302 INT_GET(block
->bb_magic
, ARCH_CONVERT
), seqno
, bno
);
4307 if (INT_GET(block
->bb_level
, ARCH_CONVERT
) != level
) {
4309 dbprintf("expected level %d got %d in btcnt block "
4311 level
, INT_GET(block
->bb_level
, ARCH_CONVERT
), seqno
, bno
);
4314 set_dbmap(seqno
, bno
, 1, DBM_BTCNT
, seqno
, bno
);
4316 if (INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) > mp
->m_alloc_mxr
[0] ||
4317 (isroot
== 0 && INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) < mp
->m_alloc_mnr
[0])) {
4318 dbprintf("bad btree nrecs (%u, min=%u, max=%u) in "
4319 "btbno block %u/%u\n",
4320 INT_GET(block
->bb_numrecs
, ARCH_CONVERT
), mp
->m_alloc_mnr
[0],
4321 mp
->m_alloc_mxr
[0], seqno
, bno
);
4325 rp
= XFS_BTREE_REC_ADDR(mp
->m_sb
.sb_blocksize
, xfs_alloc
, block
,
4326 1, mp
->m_alloc_mxr
[0]);
4327 for (i
= 0; i
< INT_GET(block
->bb_numrecs
, ARCH_CONVERT
); i
++) {
4328 check_set_dbmap(seqno
, INT_GET(rp
[i
].ar_startblock
, ARCH_CONVERT
),
4329 INT_GET(rp
[i
].ar_blockcount
, ARCH_CONVERT
), DBM_FREE1
, DBM_FREE2
,
4331 fdblocks
+= INT_GET(rp
[i
].ar_blockcount
, ARCH_CONVERT
);
4332 agffreeblks
+= INT_GET(rp
[i
].ar_blockcount
, ARCH_CONVERT
);
4333 if (INT_GET(rp
[i
].ar_blockcount
, ARCH_CONVERT
) > agflongest
)
4334 agflongest
= INT_GET(rp
[i
].ar_blockcount
, ARCH_CONVERT
);
4338 if (INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) > mp
->m_alloc_mxr
[1] ||
4339 (isroot
== 0 && INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) < mp
->m_alloc_mnr
[1])) {
4340 dbprintf("bad btree nrecs (%u, min=%u, max=%u) in btbno block "
4342 INT_GET(block
->bb_numrecs
, ARCH_CONVERT
), mp
->m_alloc_mnr
[1],
4343 mp
->m_alloc_mxr
[1], seqno
, bno
);
4347 pp
= XFS_BTREE_PTR_ADDR(mp
->m_sb
.sb_blocksize
, xfs_alloc
, block
, 1,
4348 mp
->m_alloc_mxr
[1]);
4349 for (i
= 0; i
< INT_GET(block
->bb_numrecs
, ARCH_CONVERT
); i
++)
4350 scan_sbtree(agf
, INT_GET(pp
[i
], ARCH_CONVERT
), level
, 0, scanfunc_cnt
, TYP_CNTBT
);
4355 xfs_btree_sblock_t
*ablock
,
4362 xfs_inobt_block_t
*block
= (xfs_inobt_block_t
*)ablock
;
4363 xfs_agnumber_t seqno
= INT_GET(agf
->agf_seqno
, ARCH_CONVERT
);
4369 xfs_inobt_ptr_t
*pp
;
4370 xfs_inobt_rec_t
*rp
;
4372 if (INT_GET(block
->bb_magic
, ARCH_CONVERT
) != XFS_IBT_MAGIC
) {
4373 dbprintf("bad magic # %#x in inobt block %u/%u\n",
4374 INT_GET(block
->bb_magic
, ARCH_CONVERT
), seqno
, bno
);
4378 if (INT_GET(block
->bb_level
, ARCH_CONVERT
) != level
) {
4380 dbprintf("expected level %d got %d in inobt block "
4382 level
, INT_GET(block
->bb_level
, ARCH_CONVERT
), seqno
, bno
);
4385 set_dbmap(seqno
, bno
, 1, DBM_BTINO
, seqno
, bno
);
4387 if (INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) > mp
->m_inobt_mxr
[0] ||
4388 (isroot
== 0 && INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) < mp
->m_inobt_mnr
[0])) {
4389 dbprintf("bad btree nrecs (%u, min=%u, max=%u) in "
4390 "inobt block %u/%u\n",
4391 INT_GET(block
->bb_numrecs
, ARCH_CONVERT
), mp
->m_inobt_mnr
[0],
4392 mp
->m_inobt_mxr
[0], seqno
, bno
);
4396 rp
= XFS_BTREE_REC_ADDR(mp
->m_sb
.sb_blocksize
, xfs_inobt
, block
,
4397 1, mp
->m_inobt_mxr
[0]);
4398 for (i
= 0; i
< INT_GET(block
->bb_numrecs
, ARCH_CONVERT
); i
++) {
4399 agino
= INT_GET(rp
[i
].ir_startino
, ARCH_CONVERT
);
4400 off
= XFS_INO_TO_OFFSET(mp
, agino
);
4402 if ((sbversion
& XFS_SB_VERSION_ALIGNBIT
) &&
4403 mp
->m_sb
.sb_inoalignmt
&&
4404 (XFS_INO_TO_AGBNO(mp
, agino
) %
4405 mp
->m_sb
.sb_inoalignmt
))
4406 sbversion
&= ~XFS_SB_VERSION_ALIGNBIT
;
4407 set_dbmap(seqno
, XFS_AGINO_TO_AGBNO(mp
, agino
),
4408 (xfs_extlen_t
)MAX(1,
4409 XFS_INODES_PER_CHUNK
>>
4410 mp
->m_sb
.sb_inopblog
),
4411 DBM_INODE
, seqno
, bno
);
4413 icount
+= XFS_INODES_PER_CHUNK
;
4414 agicount
+= XFS_INODES_PER_CHUNK
;
4415 ifree
+= INT_GET(rp
[i
].ir_freecount
, ARCH_CONVERT
);
4416 agifreecount
+= INT_GET(rp
[i
].ir_freecount
, ARCH_CONVERT
);
4418 set_cur(&typtab
[TYP_INODE
],
4419 XFS_AGB_TO_DADDR(mp
, seqno
,
4420 XFS_AGINO_TO_AGBNO(mp
, agino
)),
4421 (int)XFS_FSB_TO_BB(mp
, XFS_IALLOC_BLOCKS(mp
)),
4423 if (iocur_top
->data
== NULL
) {
4425 dbprintf("can't read inode block "
4428 XFS_AGINO_TO_AGBNO(mp
, agino
));
4432 for (j
= 0, nfree
= 0; j
< XFS_INODES_PER_CHUNK
; j
++) {
4433 if ((isfree
= XFS_INOBT_IS_FREE_DISK(&rp
[i
], j
)))
4435 process_inode(agf
, agino
+ j
,
4436 (xfs_dinode_t
*)((char *)iocur_top
->data
+ ((off
+ j
) << mp
->m_sb
.sb_inodelog
)),
4439 if (nfree
!= INT_GET(rp
[i
].ir_freecount
, ARCH_CONVERT
)) {
4441 dbprintf("ir_freecount/free mismatch, "
4442 "inode chunk %u/%u, freecount "
4445 INT_GET(rp
[i
].ir_freecount
, ARCH_CONVERT
), nfree
);
4452 if (INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) > mp
->m_inobt_mxr
[1] ||
4453 (isroot
== 0 && INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) < mp
->m_inobt_mnr
[1])) {
4454 dbprintf("bad btree nrecs (%u, min=%u, max=%u) in inobt block "
4456 INT_GET(block
->bb_numrecs
, ARCH_CONVERT
), mp
->m_inobt_mnr
[1],
4457 mp
->m_inobt_mxr
[1], seqno
, bno
);
4461 pp
= XFS_BTREE_PTR_ADDR(mp
->m_sb
.sb_blocksize
, xfs_inobt
, block
, 1,
4462 mp
->m_inobt_mxr
[1]);
4463 for (i
= 0; i
< INT_GET(block
->bb_numrecs
, ARCH_CONVERT
); i
++)
4464 scan_sbtree(agf
, INT_GET(pp
[i
], ARCH_CONVERT
), level
, 0, scanfunc_ino
, TYP_INOBT
);
4469 xfs_agnumber_t agno
,
4470 xfs_agblock_t agbno
,
4473 xfs_agnumber_t c_agno
,
4474 xfs_agblock_t c_agbno
)
4476 check_set_dbmap(agno
, agbno
, len
, DBM_UNKNOWN
, type
, c_agno
, c_agbno
);
4481 xfs_agnumber_t agno
,
4482 xfs_agblock_t agbno
,
4490 if (!check_inomap(agno
, agbno
, len
, id
->ino
))
4492 mayprint
= verbose
| id
->ilist
| blist_size
;
4493 for (i
= 0, idp
= &inomap
[agno
][agbno
]; i
< len
; i
++, idp
++) {
4496 (verbose
|| id
->ilist
|| CHECK_BLISTA(agno
, agbno
+ i
)))
4497 dbprintf("setting inode to %lld for block %u/%u\n",
4498 id
->ino
, agno
, agbno
+ i
);
4508 check_set_rdbmap(bno
, len
, DBM_UNKNOWN
, type
);
4521 if (!check_rinomap(bno
, len
, id
->ino
))
4523 mayprint
= verbose
| id
->ilist
| blist_size
;
4524 for (i
= 0, idp
= &inomap
[mp
->m_sb
.sb_agcount
][bno
];
4528 if (mayprint
&& (verbose
|| id
->ilist
|| CHECK_BLIST(bno
+ i
)))
4529 dbprintf("setting inode to %lld for rtblock %llu\n",
4541 id
->link_set
= nlink
;
4543 id
->security
= security
;
4544 if (verbose
|| id
->ilist
)
4545 dbprintf("inode %lld nlink %u %s dir\n", id
->ino
, nlink
,
4546 isdir
? "is" : "not");