2 * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 * Further, this software is distributed without any warranty that it is
13 * free of the rightful claim of any third person regarding infringement
14 * or the like. Any license provided herein, whether implied or
15 * otherwise, applies only to this software file. Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write the Free Software Foundation, Inc., 59
21 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
28 * For further information regarding this notice, see:
30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
48 DBM_UNKNOWN
, DBM_AGF
, DBM_AGFL
, DBM_AGI
,
49 DBM_ATTR
, DBM_BTBMAPA
, DBM_BTBMAPD
, DBM_BTBNO
,
50 DBM_BTCNT
, DBM_BTINO
, DBM_DATA
, DBM_DIR
,
51 DBM_FREE1
, DBM_FREE2
, DBM_FREELIST
, DBM_INODE
,
52 DBM_LOG
, DBM_MISSING
, DBM_QUOTA
, DBM_RTBITMAP
,
53 DBM_RTDATA
, DBM_RTFREE
, DBM_RTSUM
, DBM_SB
,
58 typedef struct inodata
{
66 struct inodata
*parent
;
69 #define MIN_INODATA_HASH_SIZE 256
70 #define MAX_INODATA_HASH_SIZE 65536
71 #define INODATA_AVG_HASH_LENGTH 8
73 typedef struct qinfo
{
79 #define QDATA_HASH_SIZE 256
80 typedef struct qdata
{
87 typedef struct blkent
{
88 xfs_fileoff_t startoff
;
90 xfs_fsblock_t blks
[1];
92 #define BLKENT_SIZE(n) \
93 (offsetof(blkent_t, blks) + (sizeof(xfs_fsblock_t) * (n)))
95 typedef struct blkmap
{
100 #define BLKMAP_SIZE(n) \
101 (offsetof(blkmap_t, ents) + (sizeof(blkent_t *) * (n)))
103 typedef struct freetab
{
106 xfs_dir2_data_off_t ents
[1];
108 #define FREETAB_SIZE(n) \
109 (offsetof(freetab_t, ents) + (sizeof(xfs_dir2_data_off_t) * (n)))
111 typedef struct dirhash
{
112 struct dirhash
*next
;
113 xfs_dir2_leaf_entry_t entry
;
116 #define DIR_HASH_SIZE 1024
117 #define DIR_HASH_FUNC(h,a) (((h) ^ (a)) % DIR_HASH_SIZE)
119 static xfs_extlen_t agffreeblks
;
120 static xfs_extlen_t agflongest
;
121 static xfs_agino_t agicount
;
122 static xfs_agino_t agifreecount
;
123 static xfs_fsblock_t
*blist
;
124 static int blist_size
;
125 static char **dbmap
; /* really dbm_t:8 */
126 static dirhash_t
**dirhash
;
128 static __uint64_t fdblocks
;
129 static __uint64_t frextents
;
130 static __uint64_t icount
;
131 static __uint64_t ifree
;
132 static inodata_t
***inodata
;
133 static int inodata_hash_size
;
134 static inodata_t
***inomap
;
137 static qdata_t
**qgdata
;
139 static qdata_t
**qudata
;
141 static unsigned sbversion
;
142 static int sbver_err
;
143 static int serious_error
;
145 static xfs_suminfo_t
*sumcompute
;
146 static xfs_suminfo_t
*sumfile
;
147 static const char *typename
[] = {
177 #define CHECK_BLIST(b) (blist_size && check_blist(b))
178 #define CHECK_BLISTA(a,b) \
179 (blist_size && check_blist(XFS_AGB_TO_FSB(mp, a, b)))
181 typedef void (*scan_lbtree_f_t
)(xfs_btree_lblock_t
*block
,
193 typedef void (*scan_sbtree_f_t
)(xfs_btree_sblock_t
*block
,
199 static void add_blist(xfs_fsblock_t bno
);
200 static void add_ilist(xfs_ino_t ino
);
201 static void addlink_inode(inodata_t
*id
);
202 static void addname_inode(inodata_t
*id
, char *name
, int namelen
);
203 static void addparent_inode(inodata_t
*id
, xfs_ino_t parent
);
204 static void blkent_append(blkent_t
**entp
, xfs_fsblock_t b
,
206 static blkent_t
*blkent_new(xfs_fileoff_t o
, xfs_fsblock_t b
,
208 static void blkent_prepend(blkent_t
**entp
, xfs_fsblock_t b
,
210 static blkmap_t
*blkmap_alloc(xfs_extnum_t
);
211 static void blkmap_free(blkmap_t
*blkmap
);
212 static xfs_fsblock_t
blkmap_get(blkmap_t
*blkmap
, xfs_fileoff_t o
);
213 static int blkmap_getn(blkmap_t
*blkmap
, xfs_fileoff_t o
, int nb
,
215 static void blkmap_grow(blkmap_t
**blkmapp
, blkent_t
**entp
,
217 static xfs_fileoff_t
blkmap_next_off(blkmap_t
*blkmap
, xfs_fileoff_t o
,
219 static void blkmap_set_blk(blkmap_t
**blkmapp
, xfs_fileoff_t o
,
221 static void blkmap_set_ext(blkmap_t
**blkmapp
, xfs_fileoff_t o
,
222 xfs_fsblock_t b
, xfs_extlen_t c
);
223 static void blkmap_shrink(blkmap_t
*blkmap
, blkent_t
**entp
);
224 static int blockfree_f(int argc
, char **argv
);
225 static int blockget_f(int argc
, char **argv
);
227 static int blocktrash_f(int argc
, char **argv
);
229 static int blockuse_f(int argc
, char **argv
);
230 static int check_blist(xfs_fsblock_t bno
);
231 static void check_dbmap(xfs_agnumber_t agno
, xfs_agblock_t agbno
,
232 xfs_extlen_t len
, dbm_t type
);
233 static int check_inomap(xfs_agnumber_t agno
, xfs_agblock_t agbno
,
234 xfs_extlen_t len
, xfs_ino_t c_ino
);
235 static void check_linkcounts(xfs_agnumber_t agno
);
236 static int check_range(xfs_agnumber_t agno
, xfs_agblock_t agbno
,
238 static void check_rdbmap(xfs_drfsbno_t bno
, xfs_extlen_t len
,
240 static int check_rinomap(xfs_drfsbno_t bno
, xfs_extlen_t len
,
242 static void check_rootdir(void);
243 static int check_rrange(xfs_drfsbno_t bno
, xfs_extlen_t len
);
244 static void check_set_dbmap(xfs_agnumber_t agno
,
245 xfs_agblock_t agbno
, xfs_extlen_t len
,
246 dbm_t type1
, dbm_t type2
,
247 xfs_agnumber_t c_agno
,
248 xfs_agblock_t c_agbno
);
249 static void check_set_rdbmap(xfs_drfsbno_t bno
, xfs_extlen_t len
,
250 dbm_t type1
, dbm_t type2
);
251 static void check_summary(void);
252 static void checknot_dbmap(xfs_agnumber_t agno
, xfs_agblock_t agbno
,
253 xfs_extlen_t len
, int typemask
);
254 static void checknot_rdbmap(xfs_drfsbno_t bno
, xfs_extlen_t len
,
256 static void dir_hash_add(xfs_dahash_t hash
,
257 xfs_dir2_dataptr_t addr
);
258 static void dir_hash_check(inodata_t
*id
, int v
);
259 static void dir_hash_done(void);
260 static void dir_hash_init(void);
261 static int dir_hash_see(xfs_dahash_t hash
,
262 xfs_dir2_dataptr_t addr
);
263 static inodata_t
*find_inode(xfs_ino_t ino
, int add
);
264 static void free_inodata(xfs_agnumber_t agno
);
265 static int init(int argc
, char **argv
);
266 static char *inode_name(xfs_ino_t ino
, inodata_t
**ipp
);
267 static int ncheck_f(int argc
, char **argv
);
268 static char *prepend_path(char *oldpath
, char *parent
);
269 static xfs_ino_t
process_block_dir_v2(blkmap_t
*blkmap
, int *dot
,
270 int *dotdot
, inodata_t
*id
);
271 static void process_bmbt_reclist(xfs_bmbt_rec_32_t
*rp
, int numrecs
,
272 dbm_t type
, inodata_t
*id
,
275 static void process_btinode(inodata_t
*id
, xfs_dinode_t
*dip
,
276 dbm_t type
, xfs_drfsbno_t
*totd
,
277 xfs_drfsbno_t
*toti
, xfs_extnum_t
*nex
,
278 blkmap_t
**blkmapp
, int whichfork
);
279 static xfs_ino_t
process_data_dir_v2(int *dot
, int *dotdot
,
280 inodata_t
*id
, int v
,
282 freetab_t
**freetabp
);
283 static xfs_dir2_data_free_t
284 *process_data_dir_v2_freefind(xfs_dir2_data_t
*data
,
285 xfs_dir2_data_unused_t
*dup
);
286 static void process_dir(xfs_dinode_t
*dip
, blkmap_t
*blkmap
,
288 static int process_dir_v1(xfs_dinode_t
*dip
, blkmap_t
*blkmap
,
289 int *dot
, int *dotdot
, inodata_t
*id
,
291 static int process_dir_v2(xfs_dinode_t
*dip
, blkmap_t
*blkmap
,
292 int *dot
, int *dotdot
, inodata_t
*id
,
294 static void process_exinode(inodata_t
*id
, xfs_dinode_t
*dip
,
295 dbm_t type
, xfs_drfsbno_t
*totd
,
296 xfs_drfsbno_t
*toti
, xfs_extnum_t
*nex
,
297 blkmap_t
**blkmapp
, int whichfork
);
298 static void process_inode(xfs_agf_t
*agf
, xfs_agino_t agino
,
299 xfs_dinode_t
*dip
, int isfree
);
300 static void process_lclinode(inodata_t
*id
, xfs_dinode_t
*dip
,
301 dbm_t type
, xfs_drfsbno_t
*totd
,
302 xfs_drfsbno_t
*toti
, xfs_extnum_t
*nex
,
303 blkmap_t
**blkmapp
, int whichfork
);
304 static xfs_ino_t
process_leaf_dir_v1(blkmap_t
*blkmap
, int *dot
,
305 int *dotdot
, inodata_t
*id
);
306 static xfs_ino_t
process_leaf_dir_v1_int(int *dot
, int *dotdot
,
308 static xfs_ino_t
process_leaf_node_dir_v2(blkmap_t
*blkmap
, int *dot
,
309 int *dotdot
, inodata_t
*id
,
310 xfs_fsize_t dirsize
);
311 static void process_leaf_node_dir_v2_free(inodata_t
*id
, int v
,
314 static void process_leaf_node_dir_v2_int(inodata_t
*id
, int v
,
317 static xfs_ino_t
process_node_dir_v1(blkmap_t
*blkmap
, int *dot
,
318 int *dotdot
, inodata_t
*id
);
319 static void process_quota(int isgrp
, inodata_t
*id
,
321 static void process_rtbitmap(blkmap_t
*blkmap
);
322 static void process_rtsummary(blkmap_t
*blkmap
);
323 static xfs_ino_t
process_sf_dir_v2(xfs_dinode_t
*dip
, int *dot
,
324 int *dotdot
, inodata_t
*id
);
325 static xfs_ino_t
process_shortform_dir_v1(xfs_dinode_t
*dip
, int *dot
,
326 int *dotdot
, inodata_t
*id
);
327 static void quota_add(xfs_dqid_t grpid
, xfs_dqid_t usrid
,
328 int dq
, xfs_qcnt_t bc
, xfs_qcnt_t ic
,
330 static void quota_add1(qdata_t
**qt
, xfs_dqid_t id
, int dq
,
331 xfs_qcnt_t bc
, xfs_qcnt_t ic
,
333 static void quota_check(char *s
, qdata_t
**qt
);
334 static void quota_init(void);
335 static void scan_ag(xfs_agnumber_t agno
);
336 static void scan_freelist(xfs_agf_t
*agf
);
337 static void scan_lbtree(xfs_fsblock_t root
, int nlevels
,
338 scan_lbtree_f_t func
, dbm_t type
,
339 inodata_t
*id
, xfs_drfsbno_t
*totd
,
340 xfs_drfsbno_t
*toti
, xfs_extnum_t
*nex
,
341 blkmap_t
**blkmapp
, int isroot
,
343 static void scan_sbtree(xfs_agf_t
*agf
, xfs_agblock_t root
,
344 int nlevels
, int isroot
,
345 scan_sbtree_f_t func
, typnm_t btype
);
346 static void scanfunc_bmap(xfs_btree_lblock_t
*ablock
, int level
,
347 dbm_t type
, xfs_fsblock_t bno
,
348 inodata_t
*id
, xfs_drfsbno_t
*totd
,
349 xfs_drfsbno_t
*toti
, xfs_extnum_t
*nex
,
350 blkmap_t
**blkmapp
, int isroot
,
352 static void scanfunc_bno(xfs_btree_sblock_t
*ablock
, int level
,
353 xfs_agf_t
*agf
, xfs_agblock_t bno
,
355 static void scanfunc_cnt(xfs_btree_sblock_t
*ablock
, int level
,
356 xfs_agf_t
*agf
, xfs_agblock_t bno
,
358 static void scanfunc_ino(xfs_btree_sblock_t
*ablock
, int level
,
359 xfs_agf_t
*agf
, xfs_agblock_t bno
,
361 static void set_dbmap(xfs_agnumber_t agno
, xfs_agblock_t agbno
,
362 xfs_extlen_t len
, dbm_t type
,
363 xfs_agnumber_t c_agno
, xfs_agblock_t c_agbno
);
364 static void set_inomap(xfs_agnumber_t agno
, xfs_agblock_t agbno
,
365 xfs_extlen_t len
, inodata_t
*id
);
366 static void set_rdbmap(xfs_drfsbno_t bno
, xfs_extlen_t len
,
368 static void set_rinomap(xfs_drfsbno_t bno
, xfs_extlen_t len
,
370 static void setlink_inode(inodata_t
*id
, nlink_t nlink
, int isdir
,
373 static const cmdinfo_t blockfree_cmd
=
374 { "blockfree", NULL
, blockfree_f
, 0, 0, 0,
375 NULL
, "free block usage information", NULL
};
376 static const cmdinfo_t blockget_cmd
=
377 { "blockget", "check", blockget_f
, 0, -1, 0,
378 "[-s|-v] [-n] [-b bno]... [-i ino] ...",
379 "get block usage and check consistency", NULL
};
381 static const cmdinfo_t blocktrash_cmd
=
382 { "blocktrash", NULL
, blocktrash_f
, 0, -1, 0,
383 "[-n count] [-x minlen] [-y maxlen] [-s seed] [-0123] [-t type] ...",
384 "trash randomly selected block(s)", NULL
};
386 static const cmdinfo_t blockuse_cmd
=
387 { "blockuse", NULL
, blockuse_f
, 0, 3, 0,
388 "[-n] [-c blockcount]",
389 "print usage for current block(s)", NULL
};
390 static const cmdinfo_t ncheck_cmd
=
391 { "ncheck", NULL
, ncheck_f
, 0, -1, 0,
393 "print inode-name pairs", NULL
};
401 blist
= xrealloc(blist
, blist_size
* sizeof(bno
));
402 blist
[blist_size
- 1] = bno
;
411 id
= find_inode(ino
, 1);
413 dbprintf("-i %lld bad inode number\n", ino
);
424 if (verbose
|| id
->ilist
)
425 dbprintf("inode %lld add link, now %u\n", id
->ino
,
435 if (!nflag
|| id
->name
)
437 id
->name
= xmalloc(namelen
+ 1);
438 memcpy(id
->name
, name
, namelen
);
439 id
->name
[namelen
] = '\0';
449 pid
= find_inode(parent
, 1);
451 if (verbose
|| id
->ilist
|| (pid
&& pid
->ilist
))
452 dbprintf("inode %lld parent %lld\n", id
->ino
, parent
);
465 *entp
= ent
= xrealloc(ent
, BLKENT_SIZE(c
+ ent
->nblks
));
466 for (i
= 0; i
< c
; i
++)
467 ent
->blks
[ent
->nblks
+ i
] = b
+ i
;
480 ent
= xmalloc(BLKENT_SIZE(c
));
483 for (i
= 0; i
< c
; i
++)
484 ent
->blks
[i
] = b
+ i
;
499 newent
= xmalloc(BLKENT_SIZE(oldent
->nblks
+ c
));
500 newent
->nblks
= oldent
->nblks
+ c
;
501 newent
->startoff
= oldent
->startoff
- c
;
502 for (i
= 0; i
< c
; i
++)
503 newent
->blks
[i
] = b
+ c
;
504 for (; i
< oldent
->nblks
+ c
; i
++)
505 newent
->blks
[i
] = oldent
->blks
[i
- c
];
518 blkmap
= xmalloc(BLKMAP_SIZE(nex
));
519 blkmap
->naents
= nex
;
531 for (i
= 0, entp
= blkmap
->ents
; i
< blkmap
->nents
; i
++, entp
++)
545 for (i
= 0, entp
= blkmap
->ents
; i
< blkmap
->nents
; i
++, entp
++) {
547 if (o
>= ent
->startoff
&& o
< ent
->startoff
+ ent
->nblks
)
548 return ent
->blks
[o
- ent
->startoff
];
567 for (i
= nex
= 0, bmp
= NULL
, entp
= blkmap
->ents
;
571 if (ent
->startoff
>= o
+ nb
)
573 if (ent
->startoff
+ ent
->nblks
<= o
)
575 for (ento
= ent
->startoff
;
576 ento
< ent
->startoff
+ ent
->nblks
&& ento
< o
+ nb
;
581 bmp
[nex
- 1].startoff
+ bmp
[nex
- 1].blockcount
==
583 bmp
[nex
- 1].startblock
+ bmp
[nex
- 1].blockcount
==
584 ent
->blks
[ento
- ent
->startoff
])
585 bmp
[nex
- 1].blockcount
++;
587 bmp
= realloc(bmp
, ++nex
* sizeof(*bmp
));
588 bmp
[nex
- 1].startoff
= ento
;
589 bmp
[nex
- 1].startblock
=
590 ent
->blks
[ento
- ent
->startoff
];
591 bmp
[nex
- 1].blockcount
= 1;
592 bmp
[nex
- 1].flag
= 0;
611 idx
= (int)(entp
- blkmap
->ents
);
612 if (blkmap
->naents
== blkmap
->nents
) {
613 blkmap
= xrealloc(blkmap
, BLKMAP_SIZE(blkmap
->nents
+ 1));
617 for (i
= blkmap
->nents
; i
> idx
; i
--)
618 blkmap
->ents
[i
] = blkmap
->ents
[i
- 1];
619 blkmap
->ents
[idx
] = newent
;
631 ent
= blkmap
->ents
[blkmap
->nents
- 1];
632 return ent
->startoff
+ ent
->nblks
;
646 if (o
== NULLFILEOFF
) {
648 ent
= blkmap
->ents
[0];
649 return ent
->startoff
;
651 entp
= &blkmap
->ents
[*t
];
653 if (o
< ent
->startoff
+ ent
->nblks
- 1)
656 if (entp
>= &blkmap
->ents
[blkmap
->nents
])
660 return ent
->startoff
;
675 for (entp
= blkmap
->ents
; entp
< &blkmap
->ents
[blkmap
->nents
]; entp
++) {
677 if (o
< ent
->startoff
- 1) {
678 ent
= blkent_new(o
, b
, 1);
679 blkmap_grow(blkmapp
, entp
, ent
);
682 if (o
== ent
->startoff
- 1) {
683 blkent_prepend(entp
, b
, 1);
686 if (o
>= ent
->startoff
&& o
< ent
->startoff
+ ent
->nblks
) {
687 ent
->blks
[o
- ent
->startoff
] = b
;
690 if (o
> ent
->startoff
+ ent
->nblks
)
692 blkent_append(entp
, b
, 1);
693 if (entp
== &blkmap
->ents
[blkmap
->nents
- 1])
697 if (ent
->startoff
+ ent
->nblks
< nextent
->startoff
)
699 blkent_append(entp
, nextent
->blks
[0], nextent
->nblks
);
700 blkmap_shrink(blkmap
, &entp
[1]);
703 ent
= blkent_new(o
, b
, 1);
704 blkmap_grow(blkmapp
, entp
, ent
);
720 if (!blkmap
->nents
) {
721 blkmap
->ents
[0] = blkent_new(o
, b
, c
);
725 entp
= &blkmap
->ents
[blkmap
->nents
- 1];
727 if (ent
->startoff
+ ent
->nblks
== o
) {
728 blkent_append(entp
, b
, c
);
731 if (ent
->startoff
+ ent
->nblks
< o
) {
732 ent
= blkent_new(o
, b
, c
);
733 blkmap_grow(blkmapp
, &blkmap
->ents
[blkmap
->nents
], ent
);
736 for (i
= 0; i
< c
; i
++)
737 blkmap_set_blk(blkmapp
, o
+ i
, b
+ i
);
749 idx
= (int)(entp
- blkmap
->ents
);
750 for (i
= idx
+ 1; i
< blkmap
->nents
; i
++)
751 blkmap
->ents
[i
] = blkmap
->ents
[i
- 1];
765 dbprintf("block usage information not allocated\n");
768 rt
= mp
->m_sb
.sb_rextents
!= 0;
769 for (c
= 0; c
< mp
->m_sb
.sb_agcount
; c
++) {
779 sumcompute
= sumfile
= NULL
;
791 * Check consistency of xfs filesystem contents.
803 dbprintf("already have block usage information\n");
806 if (!init(argc
, argv
))
808 oldprefix
= dbprefix
;
810 for (agno
= 0, sbyell
= 0; agno
< mp
->m_sb
.sb_agcount
; agno
++) {
812 if (sbver_err
> 4 && !sbyell
&& sbver_err
>= agno
) {
814 dbprintf("WARNING: this may be a newer XFS "
825 dbprefix
= oldprefix
;
829 for (agno
= 0; agno
< mp
->m_sb
.sb_agcount
; agno
++) {
831 * Check that there are no blocks either
832 * a) unaccounted for or
833 * b) bno-free but not cnt-free
835 checknot_dbmap(agno
, 0, mp
->m_sb
.sb_agblocks
,
836 (1 << DBM_UNKNOWN
) | (1 << DBM_FREE1
));
837 check_linkcounts(agno
);
839 if (mp
->m_sb
.sb_rblocks
) {
841 (xfs_extlen_t
)(mp
->m_sb
.sb_rextents
*
842 mp
->m_sb
.sb_rextsize
),
846 if (mp
->m_sb
.sb_icount
!= icount
) {
848 dbprintf("sb_icount %lld, counted %lld\n",
849 mp
->m_sb
.sb_icount
, icount
);
852 if (mp
->m_sb
.sb_ifree
!= ifree
) {
854 dbprintf("sb_ifree %lld, counted %lld\n",
855 mp
->m_sb
.sb_ifree
, ifree
);
858 if (mp
->m_sb
.sb_fdblocks
!= fdblocks
) {
860 dbprintf("sb_fdblocks %lld, counted %lld\n",
861 mp
->m_sb
.sb_fdblocks
, fdblocks
);
864 if (mp
->m_sb
.sb_frextents
!= frextents
) {
866 dbprintf("sb_frextents %lld, counted %lld\n",
867 mp
->m_sb
.sb_frextents
, frextents
);
870 if ((sbversion
& XFS_SB_VERSION_ATTRBIT
) &&
871 !XFS_SB_VERSION_HASATTR(&mp
->m_sb
)) {
873 dbprintf("sb versionnum missing attr bit %x\n",
874 XFS_SB_VERSION_ATTRBIT
);
877 if ((sbversion
& XFS_SB_VERSION_NLINKBIT
) &&
878 !XFS_SB_VERSION_HASNLINK(&mp
->m_sb
)) {
880 dbprintf("sb versionnum missing nlink bit %x\n",
881 XFS_SB_VERSION_NLINKBIT
);
884 if ((sbversion
& XFS_SB_VERSION_QUOTABIT
) &&
885 !XFS_SB_VERSION_HASQUOTA(&mp
->m_sb
)) {
887 dbprintf("sb versionnum missing quota bit %x\n",
888 XFS_SB_VERSION_QUOTABIT
);
891 if (!(sbversion
& XFS_SB_VERSION_ALIGNBIT
) &&
892 XFS_SB_VERSION_HASALIGN(&mp
->m_sb
)) {
894 dbprintf("sb versionnum extra align bit %x\n",
895 XFS_SB_VERSION_ALIGNBIT
);
899 quota_check("user", qudata
);
901 quota_check("group", qgdata
);
902 if (sbver_err
> mp
->m_sb
.sb_agcount
/ 2)
903 dbprintf("WARNING: this may be a newer XFS filesystem.\n");
906 dbprefix
= oldprefix
;
911 typedef struct ltab
{
932 static char *modestr
[] = {
933 "zeroed", "set", "flipped", "randomized"
936 len
= (int)((random() % (ltabp
->max
- ltabp
->min
+ 1)) + ltabp
->min
);
937 offset
= (int)(random() % (int)(mp
->m_sb
.sb_blocksize
* NBBY
));
940 set_cur(&typtab
[DBM_UNKNOWN
],
941 XFS_AGB_TO_DADDR(mp
, agno
, agbno
), blkbb
, DB_RING_IGN
, NULL
);
942 if ((buf
= iocur_top
->data
) == NULL
) {
943 dbprintf("can't read block %u/%u for trashing\n", agno
, agbno
);
947 for (bitno
= 0; bitno
< len
; bitno
++) {
948 bit
= (offset
+ bitno
) % (mp
->m_sb
.sb_blocksize
* NBBY
);
960 newbit
= (buf
[byte
] & mask
) == 0;
963 newbit
= (int)random() & 1;
973 printf("blocktrash: %u/%u %s block %d bit%s starting %d:%d %s\n",
974 agno
, agbno
, typename
[type
], len
, len
== 1 ? "" : "s",
975 offset
/ NBBY
, offset
% NBBY
, modestr
[mode
]);
986 xfs_drfsbno_t blocks
;
1005 dbprintf("must run blockget first\n");
1013 gettimeofday(&now
, NULL
);
1014 seed
= (unsigned int)(now
.tv_sec
^ now
.tv_usec
);
1017 goodmask
= (1 << DBM_AGF
) |
1021 (1 << DBM_BTBMAPA
) |
1022 (1 << DBM_BTBMAPD
) |
1029 (1 << DBM_RTBITMAP
) |
1032 while ((c
= getopt(argc
, argv
, "0123n:s:t:x:y:")) != EOF
) {
1047 count
= (int)strtol(optarg
, &p
, 0);
1048 if (*p
!= '\0' || count
<= 0) {
1049 dbprintf("bad blocktrash count %s\n", optarg
);
1054 seed
= (uint
)strtoul(optarg
, &p
, 0);
1058 for (i
= 0; typename
[i
]; i
++) {
1059 if (strcmp(typename
[i
], optarg
) == 0)
1062 if (!typename
[i
] || (((1 << i
) & goodmask
) == 0)) {
1063 dbprintf("bad blocktrash type %s\n", optarg
);
1069 min
= (int)strtol(optarg
, &p
, 0);
1070 if (*p
!= '\0' || min
<= 0 ||
1071 min
> mp
->m_sb
.sb_blocksize
* NBBY
) {
1072 dbprintf("bad blocktrash min %s\n", optarg
);
1077 max
= (int)strtol(optarg
, &p
, 0);
1078 if (*p
!= '\0' || max
<= 0 ||
1079 max
> mp
->m_sb
.sb_blocksize
* NBBY
) {
1080 dbprintf("bad blocktrash max %s\n", optarg
);
1085 dbprintf("bad option for blocktrash command\n");
1090 dbprintf("bad min/max for blocktrash command\n");
1095 lentab
= xmalloc(sizeof(ltab_t
));
1096 lentab
->min
= lentab
->max
= min
;
1098 for (i
= min
+ 1; i
<= max
; i
++) {
1099 if ((i
& (i
- 1)) == 0) {
1100 lentab
= xrealloc(lentab
,
1101 sizeof(ltab_t
) * (lentablen
+ 1));
1102 lentab
[lentablen
].min
= lentab
[lentablen
].max
= i
;
1105 lentab
[lentablen
- 1].max
= i
;
1107 for (blocks
= 0, agno
= 0; agno
< mp
->m_sb
.sb_agcount
; agno
++) {
1108 for (agbno
= 0, p
= dbmap
[agno
];
1109 agbno
< mp
->m_sb
.sb_agblocks
;
1111 if ((1 << *p
) & tmask
)
1116 dbprintf("blocktrash: no matching blocks\n");
1120 dbprintf("blocktrash: seed %u\n", seed
);
1122 for (i
= 0; i
< count
; i
++) {
1123 randb
= (xfs_drfsbno_t
)((((__int64_t
)random() << 32) |
1124 random()) % blocks
);
1125 for (bi
= 0, agno
= 0, done
= 0;
1126 !done
&& agno
< mp
->m_sb
.sb_agcount
;
1128 for (agbno
= 0, p
= dbmap
[agno
];
1129 agbno
< mp
->m_sb
.sb_agblocks
;
1131 if (!((1 << *p
) & tmask
))
1135 blocktrash_b(agno
, agbno
, (dbm_t
)*p
,
1136 &lentab
[random() % lentablen
], mode
);
1152 xfs_agblock_t agbno
;
1153 xfs_agnumber_t agno
;
1163 dbprintf("must run blockget first\n");
1169 fsb
= XFS_DADDR_TO_FSB(mp
, iocur_top
->off
>> BBSHIFT
);
1170 agno
= XFS_FSB_TO_AGNO(mp
, fsb
);
1171 end
= agbno
= XFS_FSB_TO_AGBNO(mp
, fsb
);
1172 while ((c
= getopt(argc
, argv
, "c:n")) != EOF
) {
1175 count
= (int)strtol(optarg
, &p
, 0);
1176 end
= agbno
+ count
- 1;
1177 if (*p
!= '\0' || count
<= 0 ||
1178 end
>= mp
->m_sb
.sb_agblocks
) {
1179 dbprintf("bad blockuse count %s\n", optarg
);
1185 dbprintf("must run blockget -n first\n");
1191 dbprintf("bad option for blockuse command\n");
1195 while (agbno
<= end
) {
1196 p
= &dbmap
[agno
][agbno
];
1197 i
= inomap
[agno
][agbno
];
1198 dbprintf("block %llu (%u/%u) type %s",
1199 (xfs_dfsbno_t
)XFS_AGB_TO_FSB(mp
, agno
, agbno
),
1200 agno
, agbno
, typename
[(dbm_t
)*p
]);
1202 dbprintf(" inode %lld", i
->ino
);
1203 if (shownames
&& (p
= inode_name(i
->ino
, NULL
))) {
1220 for (i
= 0; i
< blist_size
; i
++) {
1221 if (blist
[i
] == bno
)
1229 xfs_agnumber_t agno
,
1230 xfs_agblock_t agbno
,
1237 for (i
= 0, p
= &dbmap
[agno
][agbno
]; i
< len
; i
++, p
++) {
1238 if ((dbm_t
)*p
!= type
) {
1239 if (!sflag
|| CHECK_BLISTA(agno
, agbno
+ i
))
1240 dbprintf("block %u/%u expected type %s got "
1242 agno
, agbno
+ i
, typename
[type
],
1243 typename
[(dbm_t
)*p
]);
1252 add_command(&blockfree_cmd
);
1253 add_command(&blockget_cmd
);
1255 add_command(&blocktrash_cmd
);
1257 add_command(&blockuse_cmd
);
1258 add_command(&ncheck_cmd
);
1263 xfs_agnumber_t agno
,
1264 xfs_agblock_t agbno
,
1272 if (!check_range(agno
, agbno
, len
)) {
1273 dbprintf("blocks %u/%u..%u claimed by inode %lld\n",
1274 agno
, agbno
, agbno
+ len
- 1, c_ino
);
1277 for (i
= 0, rval
= 1, idp
= &inomap
[agno
][agbno
]; i
< len
; i
++, idp
++) {
1279 if (!sflag
|| (*idp
)->ilist
||
1280 CHECK_BLISTA(agno
, agbno
+ i
))
1281 dbprintf("block %u/%u claimed by inode %lld, "
1282 "previous inum %lld\n",
1283 agno
, agbno
+ i
, c_ino
, (*idp
)->ino
);
1293 xfs_agnumber_t agno
)
1301 for (idx
= 0; idx
< inodata_hash_size
; ht
++, idx
++) {
1304 if (ep
->link_set
!= ep
->link_add
|| ep
->link_set
== 0) {
1305 path
= inode_name(ep
->ino
, NULL
);
1306 if (!path
&& ep
->link_add
)
1307 path
= xstrdup("?");
1308 if (!sflag
|| ep
->ilist
) {
1310 dbprintf("link count mismatch "
1311 "for inode %lld (name "
1317 else if (ep
->link_set
)
1318 dbprintf("disconnected inode "
1320 ep
->ino
, ep
->link_set
);
1322 dbprintf("allocated inode %lld "
1323 "has 0 link count\n",
1329 } else if (verbose
|| ep
->ilist
) {
1330 path
= inode_name(ep
->ino
, NULL
);
1332 dbprintf("inode %lld name %s\n",
1345 xfs_agnumber_t agno
,
1346 xfs_agblock_t agbno
,
1351 if (agno
>= mp
->m_sb
.sb_agcount
||
1352 agbno
+ len
- 1 >= mp
->m_sb
.sb_agblocks
) {
1353 for (i
= 0; i
< len
; i
++) {
1354 if (!sflag
|| CHECK_BLISTA(agno
, agbno
+ i
))
1355 dbprintf("block %u/%u out of range\n",
1373 for (i
= 0, p
= &dbmap
[mp
->m_sb
.sb_agcount
][bno
]; i
< len
; i
++, p
++) {
1374 if ((dbm_t
)*p
!= type
) {
1375 if (!sflag
|| CHECK_BLIST(bno
+ i
))
1376 dbprintf("rtblock %llu expected type %s got "
1378 bno
+ i
, typename
[type
],
1379 typename
[(dbm_t
)*p
]);
1395 if (!check_rrange(bno
, len
)) {
1396 dbprintf("rtblocks %llu..%llu claimed by inode %lld\n",
1397 bno
, bno
+ len
- 1, c_ino
);
1400 for (i
= 0, rval
= 1, idp
= &inomap
[mp
->m_sb
.sb_agcount
][bno
];
1404 if (!sflag
|| (*idp
)->ilist
|| CHECK_BLIST(bno
+ i
))
1405 dbprintf("rtblock %llu claimed by inode %lld, "
1406 "previous inum %lld\n",
1407 bno
+ i
, c_ino
, (*idp
)->ino
);
1420 id
= find_inode(mp
->m_sb
.sb_rootino
, 0);
1423 dbprintf("root inode %lld is missing\n",
1424 mp
->m_sb
.sb_rootino
);
1426 } else if (!id
->isdir
) {
1427 if (!sflag
|| id
->ilist
)
1428 dbprintf("root inode %lld is not a directory\n",
1429 mp
->m_sb
.sb_rootino
);
1441 if (bno
+ len
- 1 >= mp
->m_sb
.sb_rblocks
) {
1442 for (i
= 0; i
< len
; i
++) {
1443 if (!sflag
|| CHECK_BLIST(bno
+ i
))
1444 dbprintf("rtblock %llu out of range\n",
1455 xfs_agnumber_t agno
,
1456 xfs_agblock_t agbno
,
1460 xfs_agnumber_t c_agno
,
1461 xfs_agblock_t c_agbno
)
1467 if (!check_range(agno
, agbno
, len
)) {
1468 dbprintf("blocks %u/%u..%u claimed by block %u/%u\n", agno
,
1469 agbno
, agbno
+ len
- 1, c_agno
, c_agbno
);
1472 check_dbmap(agno
, agbno
, len
, type1
);
1473 mayprint
= verbose
| blist_size
;
1474 for (i
= 0, p
= &dbmap
[agno
][agbno
]; i
< len
; i
++, p
++) {
1476 if (mayprint
&& (verbose
|| CHECK_BLISTA(agno
, agbno
+ i
)))
1477 dbprintf("setting block %u/%u to %s\n", agno
, agbno
+ i
,
1493 if (!check_rrange(bno
, len
))
1495 check_rdbmap(bno
, len
, type1
);
1496 mayprint
= verbose
| blist_size
;
1497 for (i
= 0, p
= &dbmap
[mp
->m_sb
.sb_agcount
][bno
]; i
< len
; i
++, p
++) {
1499 if (mayprint
&& (verbose
|| CHECK_BLIST(bno
+ i
)))
1500 dbprintf("setting rtblock %llu to %s\n",
1501 bno
+ i
, typename
[type2
]);
1515 for (log
= 0; log
< mp
->m_rsumlevels
; log
++) {
1517 bno
< mp
->m_sb
.sb_rbmblocks
;
1518 bno
++, csp
++, fsp
++) {
1521 dbprintf("rt summary mismatch, size %d "
1522 "block %llu, file: %d, "
1524 log
, bno
, *fsp
, *csp
);
1533 xfs_agnumber_t agno
,
1534 xfs_agblock_t agbno
,
1541 if (!check_range(agno
, agbno
, len
))
1543 for (i
= 0, p
= &dbmap
[agno
][agbno
]; i
< len
; i
++, p
++) {
1544 if ((1 << *p
) & typemask
) {
1545 if (!sflag
|| CHECK_BLISTA(agno
, agbno
+ i
))
1546 dbprintf("block %u/%u type %s not expected\n",
1547 agno
, agbno
+ i
, typename
[(dbm_t
)*p
]);
1562 if (!check_rrange(bno
, len
))
1564 for (i
= 0, p
= &dbmap
[mp
->m_sb
.sb_agcount
][bno
]; i
< len
; i
++, p
++) {
1565 if ((1 << *p
) & typemask
) {
1566 if (!sflag
|| CHECK_BLIST(bno
+ i
))
1567 dbprintf("rtblock %llu type %s not expected\n",
1568 bno
+ i
, typename
[(dbm_t
)*p
]);
1577 xfs_dir2_dataptr_t addr
)
1582 i
= DIR_HASH_FUNC(hash
, addr
);
1583 p
= malloc(sizeof(*p
));
1584 p
->next
= dirhash
[i
];
1586 p
->entry
.hashval
= hash
;
1587 p
->entry
.address
= addr
;
1599 for (i
= 0; i
< DIR_HASH_SIZE
; i
++) {
1600 for (p
= dirhash
[i
]; p
; p
= p
->next
) {
1603 if (!sflag
|| id
->ilist
|| v
)
1604 dbprintf("dir ino %lld missing leaf entry for "
1606 id
->ino
, p
->entry
.hashval
,
1620 for (i
= 0; i
< DIR_HASH_SIZE
; i
++) {
1621 for (p
= dirhash
[i
]; p
; p
= n
) {
1633 dirhash
= calloc(DIR_HASH_SIZE
, sizeof(*dirhash
));
1639 xfs_dir2_dataptr_t addr
)
1644 i
= DIR_HASH_FUNC(hash
, addr
);
1645 for (p
= dirhash
[i
]; p
; p
= p
->next
) {
1646 if (p
->entry
.hashval
== hash
&& p
->entry
.address
== addr
) {
1662 xfs_agnumber_t agno
;
1667 agno
= XFS_INO_TO_AGNO(mp
, ino
);
1668 agino
= XFS_INO_TO_AGINO(mp
, ino
);
1669 if (agno
>= mp
->m_sb
.sb_agcount
||
1670 XFS_AGINO_TO_INO(mp
, agno
, agino
) != ino
)
1672 htab
= inodata
[agno
];
1673 ih
= agino
% inodata_hash_size
;
1676 if (ent
->ino
== ino
)
1682 ent
= xcalloc(1, sizeof(*ent
));
1684 ent
->next
= htab
[ih
];
1691 xfs_agnumber_t agno
)
1699 for (i
= 0; i
< inodata_hash_size
; i
++) {
1722 if (mp
->m_sb
.sb_magicnum
!= XFS_SB_MAGIC
) {
1723 dbprintf("bad superblock magic number %x, giving up\n",
1724 mp
->m_sb
.sb_magicnum
);
1727 rt
= mp
->m_sb
.sb_rextents
!= 0;
1728 dbmap
= xmalloc((mp
->m_sb
.sb_agcount
+ rt
) * sizeof(*dbmap
));
1729 inomap
= xmalloc((mp
->m_sb
.sb_agcount
+ rt
) * sizeof(*inomap
));
1730 inodata
= xmalloc(mp
->m_sb
.sb_agcount
* sizeof(*inodata
));
1732 (int)MAX(MIN(mp
->m_sb
.sb_icount
/
1733 (INODATA_AVG_HASH_LENGTH
* mp
->m_sb
.sb_agcount
),
1734 MAX_INODATA_HASH_SIZE
),
1735 MIN_INODATA_HASH_SIZE
);
1736 for (c
= 0; c
< mp
->m_sb
.sb_agcount
; c
++) {
1737 dbmap
[c
] = xcalloc(mp
->m_sb
.sb_agblocks
, sizeof(**dbmap
));
1738 inomap
[c
] = xcalloc(mp
->m_sb
.sb_agblocks
, sizeof(**inomap
));
1739 inodata
[c
] = xcalloc(inodata_hash_size
, sizeof(**inodata
));
1742 dbmap
[c
] = xcalloc(mp
->m_sb
.sb_rblocks
, sizeof(**dbmap
));
1743 inomap
[c
] = xcalloc(mp
->m_sb
.sb_rblocks
, sizeof(**inomap
));
1744 sumfile
= xcalloc(mp
->m_rsumsize
, 1);
1745 sumcompute
= xcalloc(mp
->m_rsumsize
, 1);
1747 nflag
= sflag
= verbose
= optind
= 0;
1748 while ((c
= getopt(argc
, argv
, "b:i:npsv")) != EOF
) {
1751 bno
= atoll(optarg
);
1755 ino
= atoll(optarg
);
1771 dbprintf("bad option for blockget command\n");
1775 error
= sbver_err
= serious_error
= 0;
1776 fdblocks
= frextents
= icount
= ifree
= 0;
1777 sbversion
= XFS_SB_VERSION_4
;
1778 if (mp
->m_sb
.sb_inoalignmt
)
1779 sbversion
|= XFS_SB_VERSION_ALIGNBIT
;
1780 if ((mp
->m_sb
.sb_uquotino
&& mp
->m_sb
.sb_uquotino
!= NULLFSINO
) ||
1781 (mp
->m_sb
.sb_gquotino
&& mp
->m_sb
.sb_gquotino
!= NULLFSINO
))
1782 sbversion
|= XFS_SB_VERSION_QUOTABIT
;
1796 id
= find_inode(ino
, 0);
1801 if (id
->name
== NULL
)
1803 path
= xstrdup(id
->name
);
1804 while (id
->parent
) {
1806 if (id
->name
== NULL
)
1808 npath
= prepend_path(path
, id
->name
);
1820 xfs_agnumber_t agno
;
1833 if (!inodata
|| !nflag
) {
1834 dbprintf("must run blockget -n first\n");
1837 security
= optind
= ilist_size
= 0;
1839 while ((c
= getopt(argc
, argv
, "i:s")) != EOF
) {
1842 ino
= atoll(optarg
);
1843 ilist
= xrealloc(ilist
, (ilist_size
+ 1) *
1845 ilist
[ilist_size
++] = ino
;
1851 dbprintf("bad option -%c for ncheck command\n", c
);
1856 for (ilp
= ilist
; ilp
< &ilist
[ilist_size
]; ilp
++) {
1858 if ((p
= inode_name(ino
, &hp
))) {
1859 dbprintf("%11llu %s", ino
, p
);
1869 for (agno
= 0; agno
< mp
->m_sb
.sb_agcount
; agno
++) {
1871 for (i
= 0; i
< inodata_hash_size
; i
++) {
1873 for (hp
= ht
[i
]; hp
; hp
= hp
->next
) {
1874 ino
= XFS_AGINO_TO_INO(mp
, agno
, hp
->ino
);
1875 p
= inode_name(ino
, &id
);
1878 if (!security
|| id
->security
) {
1879 dbprintf("%11llu %s", ino
, p
);
1899 len
= (int)(strlen(oldpath
) + strlen(parent
) + 2);
1900 path
= xmalloc(len
);
1901 snprintf(path
, len
, "%s/%s", parent
, oldpath
);
1906 process_block_dir_v2(
1920 nex
= blkmap_getn(blkmap
, 0, mp
->m_dirblkfsbs
, &bmp
);
1921 v
= id
->ilist
|| verbose
;
1924 dbprintf("block 0 for directory inode %lld is "
1932 make_bbmap(&bbmap
, nex
, bmp
);
1933 set_cur(&typtab
[TYP_DIR
], XFS_FSB_TO_DADDR(mp
, bmp
->startblock
),
1934 mp
->m_dirblkfsbs
* blkbb
, DB_RING_IGN
, nex
> 1 ? &bbmap
: NULL
);
1935 for (x
= 0; !v
&& x
< nex
; x
++) {
1936 for (b
= bmp
[x
].startblock
;
1937 !v
&& b
< bmp
[x
].startblock
+ bmp
[x
].blockcount
;
1942 if (iocur_top
->data
== NULL
) {
1943 if (!sflag
|| id
->ilist
|| v
)
1944 dbprintf("can't read block 0 for directory inode "
1951 parent
= process_data_dir_v2(dot
, dotdot
, id
, v
, mp
->m_dirdatablk
,
1953 dir_hash_check(id
, v
);
1960 process_bmbt_reclist(
1961 xfs_bmbt_rec_32_t
*rp
,
1968 xfs_agblock_t agbno
;
1969 xfs_agnumber_t agno
;
1975 xfs_agblock_t iagbno
;
1976 xfs_agnumber_t iagno
;
1983 v
= verbose
|| id
->ilist
;
1984 iagno
= XFS_INO_TO_AGNO(mp
, id
->ino
);
1985 iagbno
= XFS_INO_TO_AGBNO(mp
, id
->ino
);
1986 for (i
= 0; i
< numrecs
; i
++, rp
++) {
1987 convert_extent((xfs_bmbt_rec_64_t
*)rp
, &o
, &s
, &c
, &f
);
1989 dbprintf("inode %lld extent [%lld,%lld,%lld,%d]\n",
1990 id
->ino
, o
, s
, c
, f
);
1991 if (!sflag
&& i
> 0 && op
+ cp
> o
)
1992 dbprintf("bmap rec out of order, inode %lld entry %d\n",
1996 if (type
== DBM_RTDATA
) {
1997 if (!sflag
&& s
>= mp
->m_sb
.sb_rblocks
) {
1998 dbprintf("inode %lld bad rt block number %lld, "
2003 } else if (!sflag
) {
2004 agno
= XFS_FSB_TO_AGNO(mp
, s
);
2005 agbno
= XFS_FSB_TO_AGBNO(mp
, s
);
2006 if (agno
>= mp
->m_sb
.sb_agcount
||
2007 agbno
>= mp
->m_sb
.sb_agblocks
) {
2008 dbprintf("inode %lld bad block number %lld "
2009 "[%d,%d], offset %lld\n",
2010 id
->ino
, s
, agno
, agbno
, o
);
2013 if (agbno
+ c
- 1 >= mp
->m_sb
.sb_agblocks
) {
2014 dbprintf("inode %lld bad block number %lld "
2015 "[%d,%d], offset %lld\n",
2016 id
->ino
, s
+ c
- 1, agno
,
2017 agbno
+ (xfs_agblock_t
)c
- 1, o
);
2021 if (blkmapp
&& *blkmapp
)
2022 blkmap_set_ext(blkmapp
, (xfs_fileoff_t
)o
,
2023 (xfs_fsblock_t
)s
, (xfs_extlen_t
)c
);
2024 if (type
== DBM_RTDATA
) {
2025 set_rdbmap((xfs_fsblock_t
)s
, (xfs_extlen_t
)c
,
2027 set_rinomap((xfs_fsblock_t
)s
, (xfs_extlen_t
)c
, id
);
2028 for (b
= (xfs_fsblock_t
)s
;
2029 blist_size
&& b
< s
+ c
;
2032 dbprintf("inode %lld block %lld at "
2034 id
->ino
, (xfs_dfsbno_t
)b
, o
);
2037 agno
= XFS_FSB_TO_AGNO(mp
, (xfs_fsblock_t
)s
);
2038 agbno
= XFS_FSB_TO_AGBNO(mp
, (xfs_fsblock_t
)s
);
2039 set_dbmap(agno
, agbno
, (xfs_extlen_t
)c
, type
, iagno
,
2041 set_inomap(agno
, agbno
, (xfs_extlen_t
)c
, id
);
2042 for (b
= (xfs_fsblock_t
)s
;
2043 blist_size
&& b
< s
+ c
;
2044 b
++, o
++, agbno
++) {
2046 dbprintf("inode %lld block %lld at "
2048 id
->ino
, (xfs_dfsbno_t
)b
, o
);
2060 xfs_drfsbno_t
*totd
,
2061 xfs_drfsbno_t
*toti
,
2066 xfs_bmdr_block_t
*dib
;
2069 xfs_bmbt_rec_32_t
*rp
;
2071 dib
= (xfs_bmdr_block_t
*)XFS_DFORK_PTR_ARCH(dip
, whichfork
, ARCH_NOCONVERT
);
2072 if (INT_GET(dib
->bb_level
, ARCH_CONVERT
) >= XFS_BM_MAXLEVELS(mp
, whichfork
)) {
2073 if (!sflag
|| id
->ilist
)
2074 dbprintf("level for ino %lld %s fork bmap root too "
2077 whichfork
== XFS_DATA_FORK
? "data" : "attr",
2078 INT_GET(dib
->bb_level
, ARCH_CONVERT
));
2082 if (INT_GET(dib
->bb_numrecs
, ARCH_CONVERT
) >
2083 XFS_BTREE_BLOCK_MAXRECS(XFS_DFORK_SIZE_ARCH(dip
, mp
, whichfork
, ARCH_NOCONVERT
),
2084 xfs_bmdr
, INT_GET(dib
->bb_level
, ARCH_CONVERT
) == 0)) {
2085 if (!sflag
|| id
->ilist
)
2086 dbprintf("numrecs for ino %lld %s fork bmap root too "
2089 whichfork
== XFS_DATA_FORK
? "data" : "attr",
2090 INT_GET(dib
->bb_numrecs
, ARCH_CONVERT
));
2094 if (INT_GET(dib
->bb_level
, ARCH_CONVERT
) == 0) {
2095 rp
= (xfs_bmbt_rec_32_t
*)XFS_BTREE_REC_ADDR(
2096 XFS_DFORK_SIZE_ARCH(dip
, mp
, whichfork
, ARCH_NOCONVERT
),
2098 XFS_BTREE_BLOCK_MAXRECS(XFS_DFORK_SIZE(dip
, mp
,
2101 process_bmbt_reclist(rp
, INT_GET(dib
->bb_numrecs
, ARCH_CONVERT
), type
, id
, totd
,
2103 *nex
+= INT_GET(dib
->bb_numrecs
, ARCH_CONVERT
);
2106 pp
= XFS_BTREE_PTR_ADDR(XFS_DFORK_SIZE_ARCH(dip
, mp
, whichfork
, ARCH_NOCONVERT
),
2108 XFS_BTREE_BLOCK_MAXRECS(XFS_DFORK_SIZE(dip
, mp
,
2111 for (i
= 0; i
< INT_GET(dib
->bb_numrecs
, ARCH_CONVERT
); i
++)
2112 scan_lbtree((xfs_fsblock_t
)INT_GET(pp
[i
], ARCH_CONVERT
), INT_GET(dib
->bb_level
, ARCH_CONVERT
),
2113 scanfunc_bmap
, type
, id
, totd
, toti
, nex
,
2115 whichfork
== XFS_DATA_FORK
?
2116 TYP_BMAPBTD
: TYP_BMAPBTA
);
2119 XFS_DFORK_SIZE_ARCH(dip
, mp
, whichfork
, ARCH_NOCONVERT
) / sizeof(xfs_bmbt_rec_t
)) {
2120 if (!sflag
|| id
->ilist
)
2121 dbprintf("extent count for ino %lld %s fork too low "
2122 "(%d) for file format\n",
2124 whichfork
== XFS_DATA_FORK
? "data" : "attr",
2131 process_data_dir_v2(
2137 freetab_t
**freetabp
)
2139 xfs_dir2_dataptr_t addr
;
2140 xfs_dir2_data_free_t
*bf
;
2142 xfs_dir2_block_t
*block
;
2143 xfs_dir2_block_tail_t
*btp
= NULL
;
2146 xfs_dir2_data_t
*data
;
2148 xfs_dir2_data_entry_t
*dep
;
2149 xfs_dir2_data_free_t
*dfp
;
2150 xfs_dir2_data_unused_t
*dup
;
2158 xfs_dir2_leaf_entry_t
*lep
= NULL
;
2160 xfs_ino_t parent
= 0;
2164 xfs_dir2_data_off_t
*tagp
;
2166 data
= iocur_top
->data
;
2167 block
= iocur_top
->data
;
2168 if (INT_GET(block
->hdr
.magic
, ARCH_CONVERT
) != XFS_DIR2_BLOCK_MAGIC
&&
2169 INT_GET(data
->hdr
.magic
, ARCH_CONVERT
) != XFS_DIR2_DATA_MAGIC
) {
2171 dbprintf("bad directory data magic # %#x for dir ino "
2173 INT_GET(data
->hdr
.magic
, ARCH_CONVERT
), id
->ino
, dabno
);
2177 db
= XFS_DIR2_DA_TO_DB(mp
, dabno
);
2178 bf
= data
->hdr
.bestfree
;
2179 ptr
= (char *)data
->u
;
2180 if (INT_GET(block
->hdr
.magic
, ARCH_CONVERT
) == XFS_DIR2_BLOCK_MAGIC
) {
2181 btp
= XFS_DIR2_BLOCK_TAIL_P(mp
, block
);
2182 lep
= XFS_DIR2_BLOCK_LEAF_P_ARCH(btp
, ARCH_CONVERT
);
2183 endptr
= (char *)lep
;
2184 if (endptr
<= ptr
|| endptr
> (char *)btp
) {
2185 endptr
= (char *)data
+ mp
->m_dirblksize
;
2188 dbprintf("bad block directory tail for dir ino "
2194 endptr
= (char *)data
+ mp
->m_dirblksize
;
2195 bf_err
= lastfree_err
= tag_err
= 0;
2196 count
= lastfree
= freeseen
= 0;
2197 if (INT_GET(bf
[0].length
, ARCH_CONVERT
) == 0) {
2198 bf_err
+= INT_GET(bf
[0].offset
, ARCH_CONVERT
) != 0;
2201 if (INT_GET(bf
[1].length
, ARCH_CONVERT
) == 0) {
2202 bf_err
+= INT_GET(bf
[1].offset
, ARCH_CONVERT
) != 0;
2205 if (INT_GET(bf
[2].length
, ARCH_CONVERT
) == 0) {
2206 bf_err
+= INT_GET(bf
[2].offset
, ARCH_CONVERT
) != 0;
2209 bf_err
+= INT_GET(bf
[0].length
, ARCH_CONVERT
) < INT_GET(bf
[1].length
, ARCH_CONVERT
);
2210 bf_err
+= INT_GET(bf
[1].length
, ARCH_CONVERT
) < INT_GET(bf
[2].length
, ARCH_CONVERT
);
2212 freetab
= *freetabp
;
2213 if (freetab
->naents
<= db
) {
2214 *freetabp
= freetab
=
2215 realloc(freetab
, FREETAB_SIZE(db
+ 1));
2216 for (i
= freetab
->naents
; i
< db
; i
++)
2217 freetab
->ents
[i
] = NULLDATAOFF
;
2218 freetab
->naents
= db
+ 1;
2220 if (freetab
->nents
< db
+ 1)
2221 freetab
->nents
= db
+ 1;
2222 freetab
->ents
[db
] = INT_GET(bf
[0].length
, ARCH_CONVERT
);
2224 while (ptr
< endptr
) {
2225 dup
= (xfs_dir2_data_unused_t
*)ptr
;
2226 if (INT_GET(dup
->freetag
, ARCH_CONVERT
) == XFS_DIR2_DATA_FREE_TAG
) {
2227 lastfree_err
+= lastfree
!= 0;
2228 if ((INT_GET(dup
->length
, ARCH_CONVERT
) & (XFS_DIR2_DATA_ALIGN
- 1)) ||
2229 INT_GET(dup
->length
, ARCH_CONVERT
) == 0 ||
2230 (char *)(tagp
= XFS_DIR2_DATA_UNUSED_TAG_P_ARCH(dup
, ARCH_CONVERT
)) >=
2233 dbprintf("dir %lld block %d bad free "
2241 tag_err
+= INT_GET(*tagp
, ARCH_CONVERT
) != (char *)dup
- (char *)data
;
2242 dfp
= process_data_dir_v2_freefind(data
, dup
);
2244 i
= (int)(dfp
- bf
);
2245 bf_err
+= (freeseen
& (1 << i
)) != 0;
2248 bf_err
+= INT_GET(dup
->length
, ARCH_CONVERT
) > INT_GET(bf
[2].length
, ARCH_CONVERT
);
2249 ptr
+= INT_GET(dup
->length
, ARCH_CONVERT
);
2253 dep
= (xfs_dir2_data_entry_t
*)dup
;
2254 if (dep
->namelen
== 0) {
2256 dbprintf("dir %lld block %d zero length entry "
2259 (int)((char *)dep
- (char *)data
));
2262 tagp
= XFS_DIR2_DATA_ENTRY_TAG_P(dep
);
2263 if ((char *)tagp
>= endptr
) {
2265 dbprintf("dir %lld block %d bad entry at %d\n",
2267 (int)((char *)dep
- (char *)data
));
2271 tag_err
+= INT_GET(*tagp
, ARCH_CONVERT
) != (char *)dep
- (char *)data
;
2272 addr
= XFS_DIR2_DB_OFF_TO_DATAPTR(mp
, db
,
2273 (char *)dep
- (char *)data
);
2274 hash
= libxfs_da_hashname((char *)dep
->name
, dep
->namelen
);
2275 dir_hash_add(hash
, addr
);
2276 ptr
+= XFS_DIR2_DATA_ENTSIZE(dep
->namelen
);
2279 lino
= INT_GET(dep
->inumber
, ARCH_CONVERT
);
2280 cid
= find_inode(lino
, 1);
2282 dbprintf("dir %lld block %d entry %*.*s %lld\n",
2283 id
->ino
, dabno
, dep
->namelen
, dep
->namelen
,
2289 dbprintf("dir %lld block %d entry %*.*s bad "
2290 "inode number %lld\n",
2291 id
->ino
, dabno
, dep
->namelen
,
2292 dep
->namelen
, dep
->name
, lino
);
2295 if (dep
->namelen
== 2 && dep
->name
[0] == '.' &&
2296 dep
->name
[1] == '.') {
2299 dbprintf("multiple .. entries in dir "
2300 "%lld (%lld, %lld)\n",
2301 id
->ino
, parent
, lino
);
2304 parent
= cid
? lino
: NULLFSINO
;
2306 } else if (dep
->namelen
!= 1 || dep
->name
[0] != '.') {
2310 addname_inode(cid
, (char *)dep
->name
,
2314 if (lino
!= id
->ino
) {
2316 dbprintf("dir %lld entry . inode "
2317 "number mismatch (%lld)\n",
2324 if (INT_GET(data
->hdr
.magic
, ARCH_CONVERT
) == XFS_DIR2_BLOCK_MAGIC
) {
2325 endptr
= (char *)data
+ mp
->m_dirblksize
;
2326 for (i
= stale
= 0; lep
&& i
< INT_GET(btp
->count
, ARCH_CONVERT
); i
++) {
2327 if ((char *)&lep
[i
] >= endptr
) {
2329 dbprintf("dir %lld block %d bad count "
2331 id
->ino
, dabno
, INT_GET(btp
->count
, ARCH_CONVERT
));
2335 if (INT_GET(lep
[i
].address
, ARCH_CONVERT
) == XFS_DIR2_NULL_DATAPTR
)
2337 else if (dir_hash_see(INT_GET(lep
[i
].hashval
, ARCH_CONVERT
), INT_GET(lep
[i
].address
, ARCH_CONVERT
))) {
2339 dbprintf("dir %lld block %d extra leaf "
2341 id
->ino
, dabno
, INT_GET(lep
[i
].hashval
, ARCH_CONVERT
),
2342 INT_GET(lep
[i
].address
, ARCH_CONVERT
));
2347 bf_err
+= freeseen
!= 7;
2350 dbprintf("dir %lld block %d bad bestfree data\n",
2354 if (INT_GET(data
->hdr
.magic
, ARCH_CONVERT
) == XFS_DIR2_BLOCK_MAGIC
&&
2355 count
!= INT_GET(btp
->count
, ARCH_CONVERT
) - INT_GET(btp
->stale
, ARCH_CONVERT
)) {
2357 dbprintf("dir %lld block %d bad block tail count %d "
2359 id
->ino
, dabno
, INT_GET(btp
->count
, ARCH_CONVERT
), INT_GET(btp
->stale
, ARCH_CONVERT
));
2362 if (INT_GET(data
->hdr
.magic
, ARCH_CONVERT
) == XFS_DIR2_BLOCK_MAGIC
&& stale
!= INT_GET(btp
->stale
, ARCH_CONVERT
)) {
2364 dbprintf("dir %lld block %d bad stale tail count %d\n",
2365 id
->ino
, dabno
, INT_GET(btp
->stale
, ARCH_CONVERT
));
2370 dbprintf("dir %lld block %d consecutive free entries\n",
2376 dbprintf("dir %lld block %d entry/unused tag "
2384 static xfs_dir2_data_free_t
*
2385 process_data_dir_v2_freefind(
2386 xfs_dir2_data_t
*data
,
2387 xfs_dir2_data_unused_t
*dup
)
2389 xfs_dir2_data_free_t
*dfp
;
2390 xfs_dir2_data_aoff_t off
;
2392 off
= (xfs_dir2_data_aoff_t
)((char *)dup
- (char *)data
);
2393 if (INT_GET(dup
->length
, ARCH_CONVERT
) < INT_GET(data
->hdr
.bestfree
[XFS_DIR2_DATA_FD_COUNT
- 1].length
, ARCH_CONVERT
))
2395 for (dfp
= &data
->hdr
.bestfree
[0];
2396 dfp
< &data
->hdr
.bestfree
[XFS_DIR2_DATA_FD_COUNT
];
2398 if (INT_GET(dfp
->offset
, ARCH_CONVERT
) == 0)
2400 if (INT_GET(dfp
->offset
, ARCH_CONVERT
) == off
)
2418 if (XFS_DIR_IS_V2(mp
)) {
2419 if (process_dir_v2(dip
, blkmap
, &dot
, &dotdot
, id
, &parent
))
2423 if (process_dir_v1(dip
, blkmap
, &dot
, &dotdot
, id
, &parent
))
2426 bno
= XFS_INO_TO_FSB(mp
, id
->ino
);
2428 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2429 dbprintf("no . entry for directory %lld\n", id
->ino
);
2433 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2434 dbprintf("no .. entry for directory %lld\n", id
->ino
);
2436 } else if (parent
== id
->ino
&& id
->ino
!= mp
->m_sb
.sb_rootino
) {
2437 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2438 dbprintf(". and .. same for non-root directory %lld\n",
2441 } else if (id
->ino
== mp
->m_sb
.sb_rootino
&& id
->ino
!= parent
) {
2442 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2443 dbprintf("root directory %lld has .. %lld\n", id
->ino
,
2446 } else if (parent
!= NULLFSINO
&& id
->ino
!= parent
)
2447 addparent_inode(id
, parent
);
2459 if (dip
->di_core
.di_size
<= XFS_DFORK_DSIZE_ARCH(dip
, mp
, ARCH_NOCONVERT
) &&
2460 dip
->di_core
.di_format
== XFS_DINODE_FMT_LOCAL
)
2462 process_shortform_dir_v1(dip
, dot
, dotdot
, id
);
2463 else if (dip
->di_core
.di_size
== XFS_LBSIZE(mp
) &&
2464 (dip
->di_core
.di_format
== XFS_DINODE_FMT_EXTENTS
||
2465 dip
->di_core
.di_format
== XFS_DINODE_FMT_BTREE
))
2466 *parent
= process_leaf_dir_v1(blkmap
, dot
, dotdot
, id
);
2467 else if (dip
->di_core
.di_size
>= XFS_LBSIZE(mp
) &&
2468 (dip
->di_core
.di_format
== XFS_DINODE_FMT_EXTENTS
||
2469 dip
->di_core
.di_format
== XFS_DINODE_FMT_BTREE
))
2470 *parent
= process_node_dir_v1(blkmap
, dot
, dotdot
, id
);
2472 dbprintf("bad size (%lld) or format (%d) for directory inode "
2474 dip
->di_core
.di_size
, (int)dip
->di_core
.di_format
,
2491 xfs_fileoff_t last
= 0;
2494 last
= blkmap_last_off(blkmap
);
2495 if (dip
->di_core
.di_size
<= XFS_DFORK_DSIZE_ARCH(dip
, mp
, ARCH_NOCONVERT
) &&
2496 dip
->di_core
.di_format
== XFS_DINODE_FMT_LOCAL
)
2497 *parent
= process_sf_dir_v2(dip
, dot
, dotdot
, id
);
2498 else if (last
== mp
->m_dirblkfsbs
&&
2499 (dip
->di_core
.di_format
== XFS_DINODE_FMT_EXTENTS
||
2500 dip
->di_core
.di_format
== XFS_DINODE_FMT_BTREE
))
2501 *parent
= process_block_dir_v2(blkmap
, dot
, dotdot
, id
);
2502 else if (last
>= mp
->m_dirleafblk
+ mp
->m_dirblkfsbs
&&
2503 (dip
->di_core
.di_format
== XFS_DINODE_FMT_EXTENTS
||
2504 dip
->di_core
.di_format
== XFS_DINODE_FMT_BTREE
))
2505 *parent
= process_leaf_node_dir_v2(blkmap
, dot
, dotdot
, id
,
2506 dip
->di_core
.di_size
);
2508 dbprintf("bad size (%lld) or format (%d) for directory inode "
2510 dip
->di_core
.di_size
, (int)dip
->di_core
.di_format
,
2524 xfs_drfsbno_t
*totd
,
2525 xfs_drfsbno_t
*toti
,
2530 xfs_bmbt_rec_32_t
*rp
;
2532 rp
= (xfs_bmbt_rec_32_t
*)XFS_DFORK_PTR_ARCH(dip
, whichfork
, ARCH_NOCONVERT
);
2533 *nex
= XFS_DFORK_NEXTENTS_ARCH(dip
, whichfork
, ARCH_NOCONVERT
);
2536 XFS_DFORK_SIZE_ARCH(dip
, mp
, whichfork
, ARCH_NOCONVERT
) / sizeof(xfs_bmbt_rec_32_t
)) {
2537 if (!sflag
|| id
->ilist
)
2538 dbprintf("bad number of extents %d for inode %lld\n",
2543 process_bmbt_reclist(rp
, *nex
, type
, id
, totd
, blkmapp
);
2554 xfs_fsblock_t bno
= 0;
2555 xfs_dinode_core_t tdic
;
2556 xfs_dinode_core_t
*dic
;
2557 inodata_t
*id
= NULL
;
2559 xfs_extnum_t nextents
= 0;
2562 xfs_drfsbno_t totblocks
;
2563 xfs_drfsbno_t totdblocks
= 0;
2564 xfs_drfsbno_t totiblocks
= 0;
2566 xfs_extnum_t anextents
= 0;
2567 xfs_drfsbno_t atotdblocks
= 0;
2568 xfs_drfsbno_t atotiblocks
= 0;
2572 static char okfmts
[] = {
2573 0, /* type 0 unused */
2574 1 << XFS_DINODE_FMT_DEV
, /* FIFO */
2575 1 << XFS_DINODE_FMT_DEV
, /* CHR */
2576 0, /* type 3 unused */
2577 (1 << XFS_DINODE_FMT_LOCAL
) |
2578 (1 << XFS_DINODE_FMT_EXTENTS
) |
2579 (1 << XFS_DINODE_FMT_BTREE
), /* DIR */
2580 0, /* type 5 unused */
2581 1 << XFS_DINODE_FMT_DEV
, /* BLK */
2582 0, /* type 7 unused */
2583 (1 << XFS_DINODE_FMT_EXTENTS
) |
2584 (1 << XFS_DINODE_FMT_BTREE
), /* REG */
2585 0, /* type 9 unused */
2586 (1 << XFS_DINODE_FMT_LOCAL
) |
2587 (1 << XFS_DINODE_FMT_EXTENTS
), /* LNK */
2588 0, /* type 11 unused */
2589 1 << XFS_DINODE_FMT_DEV
, /* SOCK */
2590 0, /* type 13 unused */
2591 1 << XFS_DINODE_FMT_UUID
, /* MNT */
2592 0 /* type 15 unused */
2594 static char *fmtnames
[] = {
2595 "dev", "local", "extents", "btree", "uuid"
2598 /* convert the core, then copy it back into the inode */
2599 libxfs_xlate_dinode_core((xfs_caddr_t
)&dip
->di_core
, &tdic
, 1,
2601 memcpy(&dip
->di_core
, &tdic
, sizeof(xfs_dinode_core_t
));
2604 ino
= XFS_AGINO_TO_INO(mp
, INT_GET(agf
->agf_seqno
, ARCH_CONVERT
), agino
);
2606 id
= find_inode(ino
, 1);
2607 bno
= XFS_INO_TO_FSB(mp
, ino
);
2610 if (dic
->di_magic
!= XFS_DINODE_MAGIC
) {
2611 if (!sflag
|| isfree
|| id
->ilist
|| CHECK_BLIST(bno
))
2612 dbprintf("bad magic number %#x for inode %lld\n",
2613 dic
->di_magic
, ino
);
2617 if (!XFS_DINODE_GOOD_VERSION(dic
->di_version
)) {
2618 if (!sflag
|| isfree
|| id
->ilist
|| CHECK_BLIST(bno
))
2619 dbprintf("bad version number %#x for inode %lld\n",
2620 dic
->di_version
, ino
);
2625 if (dic
->di_nblocks
!= 0) {
2626 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2627 dbprintf("bad nblocks %lld for free inode "
2629 dic
->di_nblocks
, ino
);
2632 if (dic
->di_version
== XFS_DINODE_VERSION_1
)
2633 nlink
= dic
->di_onlink
;
2635 nlink
= dic
->di_nlink
;
2637 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2638 dbprintf("bad nlink %d for free inode %lld\n",
2642 if (dic
->di_mode
!= 0) {
2643 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2644 dbprintf("bad mode %#o for free inode %lld\n",
2651 * di_mode is a 16-bit uint so no need to check the < 0 case
2653 if ((((dic
->di_mode
& IFMT
) >> 12) > 15) ||
2654 (!(okfmts
[(dic
->di_mode
& IFMT
) >> 12] & (1 << dic
->di_format
)))) {
2655 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2656 dbprintf("bad format %d for inode %lld type %#o\n",
2657 dic
->di_format
, id
->ino
, dic
->di_mode
& IFMT
);
2661 if ((unsigned int)XFS_DFORK_ASIZE_ARCH(dip
, mp
, ARCH_NOCONVERT
) >= XFS_LITINO(mp
)) {
2662 if (!sflag
|| id
->ilist
)
2663 dbprintf("bad fork offset %d for inode %lld\n",
2664 dic
->di_forkoff
, id
->ino
);
2668 if ((unsigned int)dic
->di_aformat
> XFS_DINODE_FMT_BTREE
) {
2669 if (!sflag
|| id
->ilist
)
2670 dbprintf("bad attribute format %d for inode %lld\n",
2671 dic
->di_aformat
, id
->ino
);
2675 if (verbose
|| id
->ilist
|| CHECK_BLIST(bno
))
2676 dbprintf("inode %lld mode %#o fmt %s "
2678 "nex %d anex %d nblk %lld sz %lld%s%s\n",
2679 id
->ino
, dic
->di_mode
, fmtnames
[dic
->di_format
],
2680 fmtnames
[dic
->di_aformat
],
2683 dic
->di_nblocks
, dic
->di_size
,
2684 dic
->di_flags
& XFS_DIFLAG_REALTIME
? " rt" : "",
2685 dic
->di_flags
& XFS_DIFLAG_PREALLOC
? " pre" : ""
2688 switch (dic
->di_mode
& IFMT
) {
2691 if (dic
->di_format
== XFS_DINODE_FMT_LOCAL
)
2693 blkmap
= blkmap_alloc(dic
->di_nextents
);
2696 if (dic
->di_flags
& XFS_DIFLAG_REALTIME
)
2698 else if (id
->ino
== mp
->m_sb
.sb_rbmino
) {
2699 type
= DBM_RTBITMAP
;
2700 blkmap
= blkmap_alloc(dic
->di_nextents
);
2702 } else if (id
->ino
== mp
->m_sb
.sb_rsumino
) {
2704 blkmap
= blkmap_alloc(dic
->di_nextents
);
2707 else if (id
->ino
== mp
->m_sb
.sb_uquotino
||
2708 id
->ino
== mp
->m_sb
.sb_gquotino
) {
2710 blkmap
= blkmap_alloc(dic
->di_nextents
);
2715 if (dic
->di_mode
& (ISUID
| ISGID
))
2726 if (dic
->di_version
== XFS_DINODE_VERSION_1
)
2727 setlink_inode(id
, dic
->di_onlink
, type
== DBM_DIR
, security
);
2729 sbversion
|= XFS_SB_VERSION_NLINKBIT
;
2730 setlink_inode(id
, dic
->di_nlink
, type
== DBM_DIR
, security
);
2732 switch (dic
->di_format
) {
2733 case XFS_DINODE_FMT_LOCAL
:
2734 process_lclinode(id
, dip
, type
, &totdblocks
, &totiblocks
,
2735 &nextents
, &blkmap
, XFS_DATA_FORK
);
2737 case XFS_DINODE_FMT_EXTENTS
:
2738 process_exinode(id
, dip
, type
, &totdblocks
, &totiblocks
,
2739 &nextents
, &blkmap
, XFS_DATA_FORK
);
2741 case XFS_DINODE_FMT_BTREE
:
2742 process_btinode(id
, dip
, type
, &totdblocks
, &totiblocks
,
2743 &nextents
, &blkmap
, XFS_DATA_FORK
);
2746 if (XFS_DFORK_Q_ARCH(dip
, ARCH_NOCONVERT
)) {
2747 sbversion
|= XFS_SB_VERSION_ATTRBIT
;
2748 switch (dic
->di_aformat
) {
2749 case XFS_DINODE_FMT_LOCAL
:
2750 process_lclinode(id
, dip
, DBM_ATTR
, &atotdblocks
,
2751 &atotiblocks
, &anextents
, NULL
, XFS_ATTR_FORK
);
2753 case XFS_DINODE_FMT_EXTENTS
:
2754 process_exinode(id
, dip
, DBM_ATTR
, &atotdblocks
,
2755 &atotiblocks
, &anextents
, NULL
, XFS_ATTR_FORK
);
2757 case XFS_DINODE_FMT_BTREE
:
2758 process_btinode(id
, dip
, DBM_ATTR
, &atotdblocks
,
2759 &atotiblocks
, &anextents
, NULL
, XFS_ATTR_FORK
);
2771 bc
= totdblocks
+ totiblocks
+
2772 atotdblocks
+ atotiblocks
;
2776 bc
= totiblocks
+ atotdblocks
+ atotiblocks
;
2783 quota_add(dic
->di_gid
, dic
->di_uid
, 0, bc
, ic
, rc
);
2785 totblocks
= totdblocks
+ totiblocks
+ atotdblocks
+ atotiblocks
;
2786 if (totblocks
!= dic
->di_nblocks
) {
2787 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2788 dbprintf("bad nblocks %lld for inode %lld, counted "
2790 dic
->di_nblocks
, id
->ino
, totblocks
);
2793 if (nextents
!= dic
->di_nextents
) {
2794 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2795 dbprintf("bad nextents %d for inode %lld, counted %d\n",
2796 dic
->di_nextents
, id
->ino
, nextents
);
2799 if (anextents
!= dic
->di_anextents
) {
2800 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2801 dbprintf("bad anextents %d for inode %lld, counted "
2803 dic
->di_anextents
, id
->ino
, anextents
);
2806 if (type
== DBM_DIR
)
2807 process_dir(dip
, blkmap
, id
);
2808 else if (type
== DBM_RTBITMAP
)
2809 process_rtbitmap(blkmap
);
2810 else if (type
== DBM_RTSUM
)
2811 process_rtsummary(blkmap
);
2813 * If the CHKD flag is not set, this can legitimately contain garbage;
2814 * xfs_repair may have cleared that bit.
2816 else if (type
== DBM_QUOTA
) {
2817 if (id
->ino
== mp
->m_sb
.sb_uquotino
&&
2818 (mp
->m_sb
.sb_qflags
& XFS_UQUOTA_ACCT
) &&
2819 (mp
->m_sb
.sb_qflags
& XFS_UQUOTA_CHKD
))
2820 process_quota(0, id
, blkmap
);
2821 else if (id
->ino
== mp
->m_sb
.sb_gquotino
&&
2822 (mp
->m_sb
.sb_qflags
& XFS_GQUOTA_ACCT
) &&
2823 (mp
->m_sb
.sb_qflags
& XFS_GQUOTA_CHKD
))
2824 process_quota(1, id
, blkmap
);
2827 blkmap_free(blkmap
);
2836 xfs_drfsbno_t
*totd
,
2837 xfs_drfsbno_t
*toti
,
2842 xfs_attr_shortform_t
*asf
;
2844 xfs_dinode_core_t
*dic
;
2846 dic
= &dip
->di_core
;
2847 bno
= XFS_INO_TO_FSB(mp
, id
->ino
);
2848 if (whichfork
== XFS_DATA_FORK
&&
2849 dic
->di_size
> XFS_DFORK_DSIZE_ARCH(dip
, mp
, ARCH_NOCONVERT
)) {
2850 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2851 dbprintf("local inode %lld data is too large (size "
2853 id
->ino
, dic
->di_size
);
2856 else if (whichfork
== XFS_ATTR_FORK
) {
2857 asf
= (xfs_attr_shortform_t
*)XFS_DFORK_PTR_ARCH(dip
, whichfork
, ARCH_NOCONVERT
);
2858 if (INT_GET(asf
->hdr
.totsize
, ARCH_CONVERT
) > XFS_DFORK_ASIZE_ARCH(dip
, mp
, ARCH_NOCONVERT
)) {
2859 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2860 dbprintf("local inode %lld attr is too large "
2862 id
->ino
, INT_GET(asf
->hdr
.totsize
, ARCH_CONVERT
));
2869 process_leaf_dir_v1(
2878 bno
= blkmap_get(blkmap
, 0);
2879 if (bno
== NULLFSBLOCK
) {
2880 if (!sflag
|| id
->ilist
)
2881 dbprintf("block 0 for directory inode %lld is "
2888 set_cur(&typtab
[TYP_DIR
], XFS_FSB_TO_DADDR(mp
, bno
), blkbb
, DB_RING_IGN
,
2890 if (iocur_top
->data
== NULL
) {
2891 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2892 dbprintf("can't read block 0 for directory inode "
2898 parent
= process_leaf_dir_v1_int(dot
, dotdot
, id
);
2904 process_leaf_dir_v1_int(
2911 xfs_dir_leaf_entry_t
*entry
;
2913 xfs_dir_leafblock_t
*leaf
;
2915 xfs_dir_leaf_name_t
*namest
;
2916 xfs_ino_t parent
= 0;
2919 bno
= XFS_DADDR_TO_FSB(mp
, iocur_top
->bb
);
2920 v
= verbose
|| id
->ilist
|| CHECK_BLIST(bno
);
2921 leaf
= iocur_top
->data
;
2922 if (INT_GET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
) != XFS_DIR_LEAF_MAGIC
) {
2923 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2924 dbprintf("bad directory leaf magic # %#x for dir ino "
2926 INT_GET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
), id
->ino
);
2930 entry
= &leaf
->entries
[0];
2931 for (i
= 0; i
< INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
); entry
++, i
++) {
2932 namest
= XFS_DIR_LEAF_NAMESTRUCT(leaf
, INT_GET(entry
->nameidx
, ARCH_CONVERT
));
2933 lino
=DIRINO_GET_ARCH(&namest
->inumber
, ARCH_CONVERT
);
2934 cid
= find_inode(lino
, 1);
2936 dbprintf("dir %lld entry %*.*s %lld\n", id
->ino
,
2937 entry
->namelen
, entry
->namelen
, namest
->name
,
2943 dbprintf("dir %lld entry %*.*s bad inode "
2945 id
->ino
, entry
->namelen
, entry
->namelen
,
2946 namest
->name
, lino
);
2949 if (entry
->namelen
== 2 && namest
->name
[0] == '.' &&
2950 namest
->name
[1] == '.') {
2952 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
2953 dbprintf("multiple .. entries in dir "
2954 "%lld (%lld, %lld)\n",
2955 id
->ino
, parent
, lino
);
2958 parent
= cid
? lino
: NULLFSINO
;
2960 } else if (entry
->namelen
!= 1 || namest
->name
[0] != '.') {
2964 addname_inode(cid
, (char *)namest
->name
,
2968 if (lino
!= id
->ino
) {
2970 dbprintf("dir %lld entry . inode "
2971 "number mismatch (%lld)\n",
2982 process_leaf_node_dir_v2(
2987 xfs_fsize_t dirsize
)
3003 v2
= verbose
|| id
->ilist
;
3006 freetab
= malloc(FREETAB_SIZE(dirsize
/ mp
->m_dirblksize
));
3007 freetab
->naents
= (int)(dirsize
/ mp
->m_dirblksize
);
3009 for (i
= 0; i
< freetab
->naents
; i
++)
3010 freetab
->ents
[i
] = NULLDATAOFF
;
3012 while ((dbno
= blkmap_next_off(blkmap
, dbno
, &t
)) != NULLFILEOFF
) {
3013 nex
= blkmap_getn(blkmap
, dbno
, mp
->m_dirblkfsbs
, &bmp
);
3015 for (v
= v2
, x
= 0; !v
&& x
< nex
; x
++) {
3016 for (b
= bmp
[x
].startblock
;
3017 !v
&& b
< bmp
[x
].startblock
+ bmp
[x
].blockcount
;
3022 dbprintf("dir inode %lld block %u=%llu\n", id
->ino
,
3024 (xfs_dfsbno_t
)bmp
->startblock
);
3027 make_bbmap(&bbmap
, nex
, bmp
);
3028 set_cur(&typtab
[TYP_DIR
], XFS_FSB_TO_DADDR(mp
, bmp
->startblock
),
3029 mp
->m_dirblkfsbs
* blkbb
, DB_RING_IGN
,
3030 nex
> 1 ? &bbmap
: NULL
);
3032 if (iocur_top
->data
== NULL
) {
3034 dbprintf("can't read block %u for directory "
3036 (__uint32_t
)dbno
, id
->ino
);
3039 dbno
+= mp
->m_dirblkfsbs
- 1;
3042 if (dbno
< mp
->m_dirleafblk
) {
3043 lino
= process_data_dir_v2(dot
, dotdot
, id
, v
,
3044 (xfs_dablk_t
)dbno
, &freetab
);
3048 dbprintf("multiple .. entries "
3055 } else if (dbno
< mp
->m_dirfreeblk
) {
3056 process_leaf_node_dir_v2_int(id
, v
, (xfs_dablk_t
)dbno
,
3059 process_leaf_node_dir_v2_free(id
, v
, (xfs_dablk_t
)dbno
,
3063 dbno
+= mp
->m_dirblkfsbs
- 1;
3065 dir_hash_check(id
, v
);
3067 for (i
= 0; i
< freetab
->nents
; i
++) {
3068 if (freetab
->ents
[i
] != NULLDATAOFF
) {
3070 dbprintf("missing free index for data block %d "
3071 "in dir ino %lld\n",
3072 XFS_DIR2_DB_TO_DA(mp
, i
), id
->ino
);
3081 process_leaf_node_dir_v2_free(
3087 xfs_dir2_data_off_t ent
;
3088 xfs_dir2_free_t
*free
;
3093 free
= iocur_top
->data
;
3094 if (INT_GET(free
->hdr
.magic
, ARCH_CONVERT
) != XFS_DIR2_FREE_MAGIC
) {
3096 dbprintf("bad free block magic # %#x for dir ino %lld "
3098 INT_GET(free
->hdr
.magic
, ARCH_CONVERT
), id
->ino
, dabno
);
3102 maxent
= XFS_DIR2_MAX_FREE_BESTS(mp
);
3103 if (INT_GET(free
->hdr
.firstdb
, ARCH_CONVERT
) !=
3104 XFS_DIR2_DA_TO_DB(mp
, dabno
- mp
->m_dirfreeblk
) * maxent
) {
3106 dbprintf("bad free block firstdb %d for dir ino %lld "
3108 INT_GET(free
->hdr
.firstdb
, ARCH_CONVERT
), id
->ino
, dabno
);
3112 if (INT_GET(free
->hdr
.nvalid
, ARCH_CONVERT
) > maxent
|| INT_GET(free
->hdr
.nvalid
, ARCH_CONVERT
) < 0 ||
3113 INT_GET(free
->hdr
.nused
, ARCH_CONVERT
) > maxent
|| INT_GET(free
->hdr
.nused
, ARCH_CONVERT
) < 0 ||
3114 INT_GET(free
->hdr
.nused
, ARCH_CONVERT
) > INT_GET(free
->hdr
.nvalid
, ARCH_CONVERT
)) {
3116 dbprintf("bad free block nvalid/nused %d/%d for dir "
3117 "ino %lld block %d\n",
3118 INT_GET(free
->hdr
.nvalid
, ARCH_CONVERT
), INT_GET(free
->hdr
.nused
, ARCH_CONVERT
), id
->ino
,
3123 for (used
= i
= 0; i
< INT_GET(free
->hdr
.nvalid
, ARCH_CONVERT
); i
++) {
3124 if (freetab
->nents
<= INT_GET(free
->hdr
.firstdb
, ARCH_CONVERT
) + i
)
3127 ent
= freetab
->ents
[INT_GET(free
->hdr
.firstdb
, ARCH_CONVERT
) + i
];
3128 if (ent
!= INT_GET(free
->bests
[i
], ARCH_CONVERT
)) {
3130 dbprintf("bad free block ent %d is %d should "
3131 "be %d for dir ino %lld block %d\n",
3132 i
, INT_GET(free
->bests
[i
], ARCH_CONVERT
), ent
, id
->ino
, dabno
);
3135 if (INT_GET(free
->bests
[i
], ARCH_CONVERT
) != NULLDATAOFF
)
3137 if (ent
!= NULLDATAOFF
)
3138 freetab
->ents
[INT_GET(free
->hdr
.firstdb
, ARCH_CONVERT
) + i
] = NULLDATAOFF
;
3140 if (used
!= INT_GET(free
->hdr
.nused
, ARCH_CONVERT
)) {
3142 dbprintf("bad free block nused %d should be %d for dir "
3143 "ino %lld block %d\n",
3144 INT_GET(free
->hdr
.nused
, ARCH_CONVERT
), used
, id
->ino
, dabno
);
3150 process_leaf_node_dir_v2_int(
3157 xfs_dir2_data_off_t
*lbp
;
3158 xfs_dir2_leaf_t
*leaf
;
3159 xfs_dir2_leaf_entry_t
*lep
;
3160 xfs_dir2_leaf_tail_t
*ltp
;
3161 xfs_da_intnode_t
*node
;
3164 leaf
= iocur_top
->data
;
3165 switch (INT_GET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
)) {
3166 case XFS_DIR2_LEAF1_MAGIC
:
3167 if (INT_GET(leaf
->hdr
.info
.forw
, ARCH_CONVERT
) || INT_GET(leaf
->hdr
.info
.back
, ARCH_CONVERT
)) {
3169 dbprintf("bad leaf block forw/back pointers "
3170 "%d/%d for dir ino %lld block %d\n",
3171 INT_GET(leaf
->hdr
.info
.forw
, ARCH_CONVERT
),
3172 INT_GET(leaf
->hdr
.info
.back
, ARCH_CONVERT
), id
->ino
, dabno
);
3175 if (dabno
!= mp
->m_dirleafblk
) {
3177 dbprintf("single leaf block for dir ino %lld "
3178 "block %d should be at block %d\n",
3180 (xfs_dablk_t
)mp
->m_dirleafblk
);
3183 ltp
= XFS_DIR2_LEAF_TAIL_P(mp
, leaf
);
3184 lbp
= XFS_DIR2_LEAF_BESTS_P_ARCH(ltp
, ARCH_CONVERT
);
3185 for (i
= 0; i
< INT_GET(ltp
->bestcount
, ARCH_CONVERT
); i
++) {
3186 if (freetab
->nents
<= i
|| freetab
->ents
[i
] != INT_GET(lbp
[i
], ARCH_CONVERT
)) {
3188 dbprintf("bestfree %d for dir ino %lld "
3189 "block %d doesn't match table "
3191 freetab
->nents
<= i
?
3195 XFS_DIR2_DB_TO_DA(mp
, i
),
3196 INT_GET(lbp
[i
], ARCH_CONVERT
));
3198 if (freetab
->nents
> i
)
3199 freetab
->ents
[i
] = NULLDATAOFF
;
3202 case XFS_DIR2_LEAFN_MAGIC
:
3203 /* if it's at the root location then we can check the
3204 * pointers are null XXX */
3206 case XFS_DA_NODE_MAGIC
:
3207 node
= iocur_top
->data
;
3208 if (INT_GET(node
->hdr
.level
, ARCH_CONVERT
) < 1 ||
3209 INT_GET(node
->hdr
.level
, ARCH_CONVERT
) > XFS_DA_NODE_MAXDEPTH
) {
3211 dbprintf("bad node block level %d for dir ino "
3213 INT_GET(node
->hdr
.level
, ARCH_CONVERT
), id
->ino
, dabno
);
3219 dbprintf("bad directory data magic # %#x for dir ino "
3221 INT_GET(leaf
->hdr
.info
.magic
, ARCH_CONVERT
), id
->ino
, dabno
);
3226 for (i
= stale
= 0; i
< INT_GET(leaf
->hdr
.count
, ARCH_CONVERT
); i
++) {
3227 if (INT_GET(lep
[i
].address
, ARCH_CONVERT
) == XFS_DIR2_NULL_DATAPTR
)
3229 else if (dir_hash_see(INT_GET(lep
[i
].hashval
, ARCH_CONVERT
), INT_GET(lep
[i
].address
, ARCH_CONVERT
))) {
3231 dbprintf("dir %lld block %d extra leaf entry "
3233 id
->ino
, dabno
, INT_GET(lep
[i
].hashval
, ARCH_CONVERT
),
3234 INT_GET(lep
[i
].address
, ARCH_CONVERT
));
3238 if (stale
!= INT_GET(leaf
->hdr
.stale
, ARCH_CONVERT
)) {
3240 dbprintf("dir %lld block %d stale mismatch "
3242 id
->ino
, dabno
, stale
,
3243 INT_GET(leaf
->hdr
.stale
, ARCH_CONVERT
));
3249 process_node_dir_v1(
3258 xfs_da_intnode_t
*node
;
3264 v
= verbose
|| id
->ilist
;
3267 while ((dbno
= blkmap_next_off(blkmap
, dbno
, &t
)) != NULLFILEOFF
) {
3268 bno
= blkmap_get(blkmap
, dbno
);
3269 v2
= bno
!= NULLFSBLOCK
&& CHECK_BLIST(bno
);
3270 if (bno
== NULLFSBLOCK
&& dbno
== 0) {
3272 dbprintf("can't read root block for directory "
3278 dbprintf("dir inode %lld block %u=%llu\n", id
->ino
,
3279 (__uint32_t
)dbno
, (xfs_dfsbno_t
)bno
);
3280 if (bno
== NULLFSBLOCK
)
3283 set_cur(&typtab
[TYP_DIR
], XFS_FSB_TO_DADDR(mp
, bno
), blkbb
,
3285 if ((node
= iocur_top
->data
) == NULL
) {
3286 if (!sflag
|| v
|| v2
)
3287 dbprintf("can't read block %u for directory "
3289 (__uint32_t
)dbno
, id
->ino
);
3294 if (INT_GET(node
->hdr
.info
.magic
, ARCH_CONVERT
) == XFS_DA_NODE_MAGIC
)
3296 if (INT_GET(node
->hdr
.info
.magic
, ARCH_CONVERT
) == XFS_DIR_NODE_MAGIC
)
3302 lino
= process_leaf_dir_v1_int(dot
, dotdot
, id
);
3305 if (!sflag
|| v
|| v2
)
3306 dbprintf("multiple .. entries in dir "
3336 perblock
= (int)(mp
->m_sb
.sb_blocksize
/ sizeof(*dqb
));
3337 s
= isgrp
? "group" : "user";
3338 exp_flags
= isgrp
? XFS_DQ_GROUP
: XFS_DQ_USER
;
3341 while ((qbno
= blkmap_next_off(blkmap
, qbno
, &t
)) !=
3343 bno
= blkmap_get(blkmap
, qbno
);
3344 dqid
= (xfs_dqid_t
)qbno
* perblock
;
3345 cb
= CHECK_BLIST(bno
);
3346 scicb
= !sflag
|| id
->ilist
|| cb
;
3348 set_cur(&typtab
[TYP_DQBLK
], XFS_FSB_TO_DADDR(mp
, bno
), blkbb
,
3350 if ((dqb
= iocur_top
->data
) == NULL
) {
3353 dbprintf("can't read block %lld for %s quota "
3354 "inode (fsblock %lld)\n",
3355 (xfs_dfiloff_t
)qbno
, s
,
3360 for (i
= 0; i
< perblock
; i
++, dqid
++, dqb
++) {
3361 if (verbose
|| id
->ilist
|| cb
)
3362 dbprintf("%s dqblk %lld entry %d id %d bc "
3363 "%lld ic %lld rc %lld\n",
3364 s
, (xfs_dfiloff_t
)qbno
, i
, dqid
,
3365 INT_GET(dqb
->dd_diskdq
.d_bcount
, ARCH_CONVERT
),
3366 INT_GET(dqb
->dd_diskdq
.d_icount
, ARCH_CONVERT
),
3367 INT_GET(dqb
->dd_diskdq
.d_rtbcount
, ARCH_CONVERT
));
3368 if (INT_GET(dqb
->dd_diskdq
.d_magic
, ARCH_CONVERT
) != XFS_DQUOT_MAGIC
) {
3370 dbprintf("bad magic number %#x for %s "
3371 "dqblk %lld entry %d id %d\n",
3372 INT_GET(dqb
->dd_diskdq
.d_magic
, ARCH_CONVERT
), s
,
3373 (xfs_dfiloff_t
)qbno
, i
, dqid
);
3377 if (INT_GET(dqb
->dd_diskdq
.d_version
, ARCH_CONVERT
) != XFS_DQUOT_VERSION
) {
3379 dbprintf("bad version number %#x for "
3380 "%s dqblk %lld entry %d id "
3382 INT_GET(dqb
->dd_diskdq
.d_version
, ARCH_CONVERT
), s
,
3383 (xfs_dfiloff_t
)qbno
, i
, dqid
);
3387 if (INT_GET(dqb
->dd_diskdq
.d_flags
, ARCH_CONVERT
) != exp_flags
) {
3389 dbprintf("bad flags %#x for %s dqblk "
3390 "%lld entry %d id %d\n",
3391 INT_GET(dqb
->dd_diskdq
.d_flags
, ARCH_CONVERT
), s
,
3392 (xfs_dfiloff_t
)qbno
, i
, dqid
);
3396 if (INT_GET(dqb
->dd_diskdq
.d_id
, ARCH_CONVERT
) != dqid
) {
3398 dbprintf("bad id %d for %s dqblk %lld "
3400 INT_GET(dqb
->dd_diskdq
.d_id
, ARCH_CONVERT
), s
,
3401 (xfs_dfiloff_t
)qbno
, i
, dqid
);
3405 quota_add(isgrp
? dqid
: -1, isgrp
? -1 : dqid
, 1,
3406 INT_GET(dqb
->dd_diskdq
.d_bcount
, ARCH_CONVERT
),
3407 INT_GET(dqb
->dd_diskdq
.d_icount
, ARCH_CONVERT
),
3408 INT_GET(dqb
->dd_diskdq
.d_rtbcount
, ARCH_CONVERT
));
3418 #define xfs_highbit64 libxfs_highbit64 /* for XFS_RTBLOCKLOG macro */
3421 xfs_fileoff_t bmbno
;
3428 xfs_drfsbno_t rtbno
;
3432 xfs_rtword_t
*words
;
3434 bitsperblock
= mp
->m_sb
.sb_blocksize
* NBBY
;
3435 bit
= extno
= prevbit
= start_bmbno
= start_bit
= 0;
3436 bmbno
= NULLFILEOFF
;
3437 while ((bmbno
= blkmap_next_off(blkmap
, bmbno
, &t
)) !=
3439 bno
= blkmap_get(blkmap
, bmbno
);
3440 if (bno
== NULLFSBLOCK
) {
3442 dbprintf("block %lld for rtbitmap inode is "
3444 (xfs_dfiloff_t
)bmbno
);
3449 set_cur(&typtab
[TYP_RTBITMAP
], XFS_FSB_TO_DADDR(mp
, bno
), blkbb
,
3451 if ((words
= iocur_top
->data
) == NULL
) {
3454 dbprintf("can't read block %lld for rtbitmap "
3456 (xfs_dfiloff_t
)bmbno
);
3461 bit
< bitsperblock
&& extno
< mp
->m_sb
.sb_rextents
;
3463 if (isset(words
, bit
)) {
3464 rtbno
= extno
* mp
->m_sb
.sb_rextsize
;
3465 set_rdbmap(rtbno
, mp
->m_sb
.sb_rextsize
,
3469 start_bmbno
= (int)bmbno
;
3473 } else if (prevbit
== 1) {
3474 len
= ((int)bmbno
- start_bmbno
) *
3475 bitsperblock
+ (bit
- start_bit
);
3476 log
= XFS_RTBLOCKLOG(len
);
3477 offs
= XFS_SUMOFFS(mp
, log
, start_bmbno
);
3483 if (extno
== mp
->m_sb
.sb_rextents
)
3487 len
= ((int)bmbno
- start_bmbno
) * bitsperblock
+
3489 log
= XFS_RTBLOCKLOG(len
);
3490 offs
= XFS_SUMOFFS(mp
, log
, start_bmbno
);
3501 xfs_fileoff_t sumbno
;
3504 sumbno
= NULLFILEOFF
;
3505 while ((sumbno
= blkmap_next_off(blkmap
, sumbno
, &t
)) !=
3507 bno
= blkmap_get(blkmap
, sumbno
);
3508 if (bno
== NULLFSBLOCK
) {
3510 dbprintf("block %lld for rtsummary inode is "
3512 (xfs_dfiloff_t
)sumbno
);
3517 set_cur(&typtab
[TYP_RTSUMMARY
], XFS_FSB_TO_DADDR(mp
, bno
),
3518 blkbb
, DB_RING_IGN
, NULL
);
3519 if ((bytes
= iocur_top
->data
) == NULL
) {
3521 dbprintf("can't read block %lld for rtsummary "
3523 (xfs_dfiloff_t
)sumbno
);
3527 memcpy((char *)sumfile
+ sumbno
* mp
->m_sb
.sb_blocksize
, bytes
,
3528 mp
->m_sb
.sb_blocksize
);
3546 xfs_dir2_sf_entry_t
*sfe
;
3549 sf
= &dip
->di_u
.di_dir2sf
;
3551 v
= verbose
|| id
->ilist
;
3553 dbprintf("dir %lld entry . %lld\n", id
->ino
, id
->ino
);
3555 sfe
= XFS_DIR2_SF_FIRSTENTRY(sf
);
3556 offset
= XFS_DIR2_DATA_FIRST_OFFSET
;
3557 for (i
= INT_GET(sf
->hdr
.count
, ARCH_CONVERT
) - 1, i8
= 0; i
>= 0; i
--) {
3558 if ((__psint_t
)sfe
+ XFS_DIR2_SF_ENTSIZE_BYENTRY(sf
, sfe
) -
3559 (__psint_t
)sf
> dip
->di_core
.di_size
) {
3561 dbprintf("dir %llu bad size in entry at %d\n",
3563 (int)((char *)sfe
- (char *)sf
));
3567 lino
= XFS_DIR2_SF_GET_INUMBER_ARCH(sf
, XFS_DIR2_SF_INUMBERP(sfe
), ARCH_CONVERT
);
3568 if (lino
> XFS_DIR2_MAX_SHORT_INUM
)
3570 cid
= find_inode(lino
, 1);
3573 dbprintf("dir %lld entry %*.*s bad inode "
3575 id
->ino
, sfe
->namelen
, sfe
->namelen
,
3582 addname_inode(cid
, (char *)sfe
->name
, sfe
->namelen
);
3585 dbprintf("dir %lld entry %*.*s offset %d %lld\n",
3586 id
->ino
, sfe
->namelen
, sfe
->namelen
, sfe
->name
,
3587 XFS_DIR2_SF_GET_OFFSET_ARCH(sfe
, ARCH_CONVERT
), lino
);
3588 if (XFS_DIR2_SF_GET_OFFSET_ARCH(sfe
, ARCH_CONVERT
) < offset
) {
3590 dbprintf("dir %lld entry %*.*s bad offset %d\n",
3591 id
->ino
, sfe
->namelen
, sfe
->namelen
,
3592 sfe
->name
, XFS_DIR2_SF_GET_OFFSET_ARCH(sfe
, ARCH_CONVERT
));
3596 XFS_DIR2_SF_GET_OFFSET_ARCH(sfe
, ARCH_CONVERT
) +
3597 XFS_DIR2_DATA_ENTSIZE(sfe
->namelen
);
3598 sfe
= XFS_DIR2_SF_NEXTENTRY(sf
, sfe
);
3600 if (i
< 0 && (__psint_t
)sfe
- (__psint_t
)sf
!= dip
->di_core
.di_size
) {
3602 dbprintf("dir %llu size is %lld, should be %u\n",
3603 id
->ino
, dip
->di_core
.di_size
,
3604 (uint
)((char *)sfe
- (char *)sf
));
3607 if (offset
+ (INT_GET(sf
->hdr
.count
, ARCH_CONVERT
) + 2) * sizeof(xfs_dir2_leaf_entry_t
) +
3608 sizeof(xfs_dir2_block_tail_t
) > mp
->m_dirblksize
) {
3610 dbprintf("dir %llu offsets too high\n", id
->ino
);
3613 lino
= XFS_DIR2_SF_GET_INUMBER_ARCH(sf
, &sf
->hdr
.parent
, ARCH_CONVERT
);
3614 if (lino
> XFS_DIR2_MAX_SHORT_INUM
)
3616 cid
= find_inode(lino
, 1);
3621 dbprintf("dir %lld entry .. bad inode number %lld\n",
3626 dbprintf("dir %lld entry .. %lld\n", id
->ino
, lino
);
3627 if (i8
!= sf
->hdr
.i8count
) {
3629 dbprintf("dir %lld i8count mismatch is %d should be "
3631 id
->ino
, sf
->hdr
.i8count
, i8
);
3635 return cid
? lino
: NULLFSINO
;
3639 process_shortform_dir_v1(
3648 xfs_dir_shortform_t
*sf
;
3649 xfs_dir_sf_entry_t
*sfe
;
3652 sf
= &dip
->di_u
.di_dirsf
;
3654 v
= verbose
|| id
->ilist
;
3656 dbprintf("dir %lld entry . %lld\n", id
->ino
, id
->ino
);
3659 for (i
= INT_GET(sf
->hdr
.count
, ARCH_CONVERT
) - 1; i
>= 0; i
--) {
3660 lino
= DIRINO_GET_ARCH(&sfe
->inumber
, ARCH_CONVERT
);
3661 cid
= find_inode(lino
, 1);
3664 dbprintf("dir %lld entry %*.*s bad inode "
3666 id
->ino
, sfe
->namelen
, sfe
->namelen
,
3673 addname_inode(cid
, (char *)sfe
->name
, sfe
->namelen
);
3676 dbprintf("dir %lld entry %*.*s %lld\n", id
->ino
,
3677 sfe
->namelen
, sfe
->namelen
, sfe
->name
, lino
);
3678 sfe
= XFS_DIR_SF_NEXTENTRY(sfe
);
3680 if ((__psint_t
)sfe
- (__psint_t
)sf
!= dip
->di_core
.di_size
)
3681 dbprintf("dir %llu size is %lld, should be %d\n",
3682 id
->ino
, dip
->di_core
.di_size
,
3683 (int)((char *)sfe
- (char *)sf
));
3684 lino
=DIRINO_GET_ARCH(&sf
->hdr
.parent
, ARCH_CONVERT
);
3685 cid
= find_inode(lino
, 1);
3690 dbprintf("dir %lld entry .. bad inode number %lld\n",
3695 dbprintf("dir %lld entry .. %lld\n", id
->ino
, lino
);
3697 return cid
? lino
: NULLFSINO
;
3709 if (qudo
&& usrid
!= -1)
3710 quota_add1(qudata
, usrid
, dq
, bc
, ic
, rc
);
3711 if (qgdo
&& grpid
!= -1)
3712 quota_add1(qgdata
, grpid
, dq
, bc
, ic
, rc
);
3728 qh
= (int)((__uint32_t
)id
% QDATA_HASH_SIZE
);
3732 qi
= dq
? &qe
->dq
: &qe
->count
;
3740 qe
= xmalloc(sizeof(*qe
));
3742 qi
= dq
? &qe
->dq
: &qe
->count
;
3746 qi
= dq
? &qe
->count
: &qe
->dq
;
3747 qi
->bc
= qi
->ic
= qi
->rc
= 0;
3761 for (i
= 0; i
< QDATA_HASH_SIZE
; i
++) {
3765 if (qp
->count
.bc
!= qp
->dq
.bc
||
3766 qp
->count
.ic
!= qp
->dq
.ic
||
3767 qp
->count
.rc
!= qp
->dq
.rc
) {
3769 dbprintf("%s quota id %d, have/exp",
3771 if (qp
->count
.bc
!= qp
->dq
.bc
)
3772 dbprintf(" bc %lld/%lld",
3775 if (qp
->count
.ic
!= qp
->dq
.ic
)
3776 dbprintf(" ic %lld/%lld",
3779 if (qp
->count
.rc
!= qp
->dq
.rc
)
3780 dbprintf(" rc %lld/%lld",
3797 qudo
= mp
->m_sb
.sb_uquotino
!= 0 &&
3798 mp
->m_sb
.sb_uquotino
!= NULLFSINO
&&
3799 (mp
->m_sb
.sb_qflags
& XFS_UQUOTA_ACCT
) &&
3800 (mp
->m_sb
.sb_qflags
& XFS_UQUOTA_CHKD
);
3801 qgdo
= mp
->m_sb
.sb_gquotino
!= 0 &&
3802 mp
->m_sb
.sb_gquotino
!= NULLFSINO
&&
3803 (mp
->m_sb
.sb_qflags
& XFS_GQUOTA_ACCT
) &&
3804 (mp
->m_sb
.sb_qflags
& XFS_GQUOTA_CHKD
);
3806 qudata
= xcalloc(QDATA_HASH_SIZE
, sizeof(qdata_t
*));
3808 qgdata
= xcalloc(QDATA_HASH_SIZE
, sizeof(qdata_t
*));
3813 xfs_agnumber_t agno
)
3821 agffreeblks
= agflongest
= 0;
3822 agicount
= agifreecount
= 0;
3824 set_cur(&typtab
[TYP_SB
], XFS_AG_DADDR(mp
, agno
, XFS_SB_DADDR
), 1,
3827 if (!iocur_top
->data
) {
3828 dbprintf("can't read superblock for ag %u\n", agno
);
3834 libxfs_xlate_sb(iocur_top
->data
, sb
, 1, ARCH_CONVERT
, XFS_SB_ALL_BITS
);
3836 if (sb
->sb_magicnum
!= XFS_SB_MAGIC
) {
3838 dbprintf("bad sb magic # %#x in ag %u\n",
3839 sb
->sb_magicnum
, agno
);
3842 if (!XFS_SB_GOOD_VERSION(sb
)) {
3844 dbprintf("bad sb version # %#x in ag %u\n",
3845 sb
->sb_versionnum
, agno
);
3849 if (agno
== 0 && sb
->sb_inprogress
!= 0) {
3851 dbprintf("mkfs not completed successfully\n");
3854 set_dbmap(agno
, XFS_SB_BLOCK(mp
), 1, DBM_SB
, agno
, XFS_SB_BLOCK(mp
));
3855 if (sb
->sb_logstart
&& XFS_FSB_TO_AGNO(mp
, sb
->sb_logstart
) == agno
)
3856 set_dbmap(agno
, XFS_FSB_TO_AGBNO(mp
, sb
->sb_logstart
),
3857 sb
->sb_logblocks
, DBM_LOG
, agno
, XFS_SB_BLOCK(mp
));
3859 set_cur(&typtab
[TYP_AGF
], XFS_AG_DADDR(mp
, agno
, XFS_AGF_DADDR
), 1,
3861 if ((agf
= iocur_top
->data
) == NULL
) {
3862 dbprintf("can't read agf block for ag %u\n", agno
);
3868 if (INT_GET(agf
->agf_magicnum
, ARCH_CONVERT
) != XFS_AGF_MAGIC
) {
3870 dbprintf("bad agf magic # %#x in ag %u\n",
3871 INT_GET(agf
->agf_magicnum
, ARCH_CONVERT
), agno
);
3874 if (!XFS_AGF_GOOD_VERSION(INT_GET(agf
->agf_versionnum
, ARCH_CONVERT
))) {
3876 dbprintf("bad agf version # %#x in ag %u\n",
3877 INT_GET(agf
->agf_versionnum
, ARCH_CONVERT
), agno
);
3880 if (XFS_SB_BLOCK(mp
) != XFS_AGF_BLOCK(mp
))
3881 set_dbmap(agno
, XFS_AGF_BLOCK(mp
), 1, DBM_AGF
, agno
,
3883 if (sb
->sb_agblocks
> INT_GET(agf
->agf_length
, ARCH_CONVERT
))
3884 set_dbmap(agno
, INT_GET(agf
->agf_length
, ARCH_CONVERT
),
3885 sb
->sb_agblocks
- INT_GET(agf
->agf_length
, ARCH_CONVERT
),
3886 DBM_MISSING
, agno
, XFS_SB_BLOCK(mp
));
3888 set_cur(&typtab
[TYP_AGI
], XFS_AG_DADDR(mp
, agno
, XFS_AGI_DADDR
), 1,
3890 if ((agi
= iocur_top
->data
) == NULL
) {
3891 dbprintf("can't read agi block for ag %u\n", agno
);
3898 if (INT_GET(agi
->agi_magicnum
, ARCH_CONVERT
) != XFS_AGI_MAGIC
) {
3900 dbprintf("bad agi magic # %#x in ag %u\n",
3901 INT_GET(agi
->agi_magicnum
, ARCH_CONVERT
), agno
);
3904 if (!XFS_AGI_GOOD_VERSION(INT_GET(agi
->agi_versionnum
, ARCH_CONVERT
))) {
3906 dbprintf("bad agi version # %#x in ag %u\n",
3907 INT_GET(agi
->agi_versionnum
, ARCH_CONVERT
), agno
);
3910 if (XFS_SB_BLOCK(mp
) != XFS_AGI_BLOCK(mp
) &&
3911 XFS_AGF_BLOCK(mp
) != XFS_AGI_BLOCK(mp
))
3912 set_dbmap(agno
, XFS_AGI_BLOCK(mp
), 1, DBM_AGI
, agno
,
3917 INT_GET(agf
->agf_roots
[XFS_BTNUM_BNO
], ARCH_CONVERT
),
3918 INT_GET(agf
->agf_levels
[XFS_BTNUM_BNO
], ARCH_CONVERT
),
3919 1, scanfunc_bno
, TYP_BNOBT
);
3922 INT_GET(agf
->agf_roots
[XFS_BTNUM_CNT
], ARCH_CONVERT
),
3923 INT_GET(agf
->agf_levels
[XFS_BTNUM_CNT
], ARCH_CONVERT
),
3924 1, scanfunc_cnt
, TYP_CNTBT
);
3926 INT_GET(agi
->agi_root
, ARCH_CONVERT
),
3927 INT_GET(agi
->agi_level
, ARCH_CONVERT
),
3928 1, scanfunc_ino
, TYP_INOBT
);
3929 if (INT_GET(agf
->agf_freeblks
, ARCH_CONVERT
) != agffreeblks
) {
3931 dbprintf("agf_freeblks %u, counted %u in ag %u\n",
3932 INT_GET(agf
->agf_freeblks
, ARCH_CONVERT
),
3936 if (INT_GET(agf
->agf_longest
, ARCH_CONVERT
) != agflongest
) {
3938 dbprintf("agf_longest %u, counted %u in ag %u\n",
3939 INT_GET(agf
->agf_longest
, ARCH_CONVERT
),
3943 if (INT_GET(agi
->agi_count
, ARCH_CONVERT
) != agicount
) {
3945 dbprintf("agi_count %u, counted %u in ag %u\n",
3946 INT_GET(agi
->agi_count
, ARCH_CONVERT
),
3950 if (INT_GET(agi
->agi_freecount
, ARCH_CONVERT
) != agifreecount
) {
3952 dbprintf("agi_freecount %u, counted %u in ag %u\n",
3953 INT_GET(agi
->agi_freecount
, ARCH_CONVERT
),
3954 agifreecount
, agno
);
3957 for (i
= 0; i
< XFS_AGI_UNLINKED_BUCKETS
; i
++) {
3958 if (INT_GET(agi
->agi_unlinked
[i
], ARCH_CONVERT
) != NULLAGINO
) {
3960 xfs_agino_t agino
=INT_GET(agi
->agi_unlinked
[i
], ARCH_CONVERT
);
3961 dbprintf("agi unlinked bucket %d is %u in ag "
3962 "%u (inode=%lld)\n", i
, agino
, agno
,
3963 XFS_AGINO_TO_INO(mp
, agno
, agino
));
3977 xfs_agnumber_t seqno
= INT_GET(agf
->agf_seqno
, ARCH_CONVERT
);
3983 if (XFS_SB_BLOCK(mp
) != XFS_AGFL_BLOCK(mp
) &&
3984 XFS_AGF_BLOCK(mp
) != XFS_AGFL_BLOCK(mp
) &&
3985 XFS_AGI_BLOCK(mp
) != XFS_AGFL_BLOCK(mp
))
3986 set_dbmap(seqno
, XFS_AGFL_BLOCK(mp
), 1, DBM_AGFL
, seqno
,
3988 if (INT_GET(agf
->agf_flcount
, ARCH_CONVERT
) == 0)
3991 set_cur(&typtab
[TYP_AGFL
],
3992 XFS_AG_DADDR(mp
, seqno
, XFS_AGFL_DADDR
), 1, DB_RING_IGN
, NULL
);
3993 if ((agfl
= iocur_top
->data
) == NULL
) {
3994 dbprintf("can't read agfl block for ag %u\n", seqno
);
3998 i
= INT_GET(agf
->agf_flfirst
, ARCH_CONVERT
);
4001 bno
= INT_GET(agfl
->agfl_bno
[i
], ARCH_CONVERT
);
4002 set_dbmap(seqno
, bno
, 1, DBM_FREELIST
, seqno
,
4003 XFS_AGFL_BLOCK(mp
));
4005 if (i
== INT_GET(agf
->agf_fllast
, ARCH_CONVERT
))
4007 if (++i
== XFS_AGFL_SIZE
)
4010 if (count
!= INT_GET(agf
->agf_flcount
, ARCH_CONVERT
)) {
4012 dbprintf("freeblk count %u != flcount %u in ag %u\n",
4013 count
, INT_GET(agf
->agf_flcount
, ARCH_CONVERT
),
4025 scan_lbtree_f_t func
,
4028 xfs_drfsbno_t
*totd
,
4029 xfs_drfsbno_t
*toti
,
4036 set_cur(&typtab
[btype
], XFS_FSB_TO_DADDR(mp
, root
), blkbb
, DB_RING_IGN
,
4038 if (iocur_top
->data
== NULL
) {
4040 dbprintf("can't read btree block %u/%u\n",
4041 XFS_FSB_TO_AGNO(mp
, root
),
4042 XFS_FSB_TO_AGBNO(mp
, root
));
4046 (*func
)(iocur_top
->data
, nlevels
- 1, type
, root
, id
, totd
, toti
, nex
,
4047 blkmapp
, isroot
, btype
);
4057 scan_sbtree_f_t func
,
4060 xfs_agnumber_t seqno
= INT_GET(agf
->agf_seqno
, ARCH_CONVERT
);
4063 set_cur(&typtab
[btype
],
4064 XFS_AGB_TO_DADDR(mp
, seqno
, root
), blkbb
, DB_RING_IGN
, NULL
);
4065 if (iocur_top
->data
== NULL
) {
4067 dbprintf("can't read btree block %u/%u\n", seqno
, root
);
4071 (*func
)(iocur_top
->data
, nlevels
- 1, agf
, root
, isroot
);
4077 xfs_btree_lblock_t
*ablock
,
4082 xfs_drfsbno_t
*totd
,
4083 xfs_drfsbno_t
*toti
,
4089 xfs_agblock_t agbno
;
4090 xfs_agnumber_t agno
;
4091 xfs_bmbt_block_t
*block
= (xfs_bmbt_block_t
*)ablock
;
4094 xfs_bmbt_rec_32_t
*rp
;
4096 agno
= XFS_FSB_TO_AGNO(mp
, bno
);
4097 agbno
= XFS_FSB_TO_AGBNO(mp
, bno
);
4098 if (INT_GET(block
->bb_magic
, ARCH_CONVERT
) != XFS_BMAP_MAGIC
) {
4099 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
4100 dbprintf("bad magic # %#x in inode %lld bmbt block "
4102 INT_GET(block
->bb_magic
, ARCH_CONVERT
), id
->ino
, agno
, agbno
);
4105 if (INT_GET(block
->bb_level
, ARCH_CONVERT
) != level
) {
4106 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
4107 dbprintf("expected level %d got %d in inode %lld bmbt "
4109 level
, INT_GET(block
->bb_level
, ARCH_CONVERT
), id
->ino
, agno
, agbno
);
4112 set_dbmap(agno
, agbno
, 1, type
, agno
, agbno
);
4113 set_inomap(agno
, agbno
, 1, id
);
4116 if (INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) > mp
->m_bmap_dmxr
[0] ||
4117 (isroot
== 0 && INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) < mp
->m_bmap_dmnr
[0])) {
4118 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
4119 dbprintf("bad btree nrecs (%u, min=%u, max=%u) "
4120 "in inode %lld bmap block %lld\n",
4121 INT_GET(block
->bb_numrecs
, ARCH_CONVERT
), mp
->m_bmap_dmnr
[0],
4122 mp
->m_bmap_dmxr
[0], id
->ino
,
4127 rp
= (xfs_bmbt_rec_32_t
*)
4128 XFS_BTREE_REC_ADDR(mp
->m_sb
.sb_blocksize
, xfs_bmbt
,
4129 block
, 1, mp
->m_bmap_dmxr
[0]);
4130 *nex
+= INT_GET(block
->bb_numrecs
, ARCH_CONVERT
);
4131 process_bmbt_reclist(rp
, INT_GET(block
->bb_numrecs
, ARCH_CONVERT
), type
, id
, totd
,
4135 if (INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) > mp
->m_bmap_dmxr
[1] ||
4136 (isroot
== 0 && INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) < mp
->m_bmap_dmnr
[1])) {
4137 if (!sflag
|| id
->ilist
|| CHECK_BLIST(bno
))
4138 dbprintf("bad btree nrecs (%u, min=%u, max=%u) in "
4139 "inode %lld bmap block %lld\n",
4140 INT_GET(block
->bb_numrecs
, ARCH_CONVERT
), mp
->m_bmap_dmnr
[1],
4141 mp
->m_bmap_dmxr
[1], id
->ino
, (xfs_dfsbno_t
)bno
);
4145 pp
= XFS_BTREE_PTR_ADDR(mp
->m_sb
.sb_blocksize
, xfs_bmbt
, block
, 1,
4146 mp
->m_bmap_dmxr
[0]);
4147 for (i
= 0; i
< INT_GET(block
->bb_numrecs
, ARCH_CONVERT
); i
++)
4148 scan_lbtree(INT_GET(pp
[i
], ARCH_CONVERT
), level
, scanfunc_bmap
, type
, id
, totd
, toti
,
4149 nex
, blkmapp
, 0, btype
);
4154 xfs_btree_sblock_t
*ablock
,
4160 xfs_alloc_block_t
*block
= (xfs_alloc_block_t
*)ablock
;
4162 xfs_alloc_ptr_t
*pp
;
4163 xfs_alloc_rec_t
*rp
;
4164 xfs_agnumber_t seqno
= INT_GET(agf
->agf_seqno
, ARCH_CONVERT
);
4166 if (INT_GET(block
->bb_magic
, ARCH_CONVERT
) != XFS_ABTB_MAGIC
) {
4167 dbprintf("bad magic # %#x in btbno block %u/%u\n",
4168 INT_GET(block
->bb_magic
, ARCH_CONVERT
), seqno
, bno
);
4173 if (INT_GET(block
->bb_level
, ARCH_CONVERT
) != level
) {
4175 dbprintf("expected level %d got %d in btbno block "
4177 level
, INT_GET(block
->bb_level
, ARCH_CONVERT
), seqno
, bno
);
4180 set_dbmap(seqno
, bno
, 1, DBM_BTBNO
, seqno
, bno
);
4182 if (INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) > mp
->m_alloc_mxr
[0] ||
4183 (isroot
== 0 && INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) < mp
->m_alloc_mnr
[0])) {
4184 dbprintf("bad btree nrecs (%u, min=%u, max=%u) in "
4185 "btbno block %u/%u\n",
4186 INT_GET(block
->bb_numrecs
, ARCH_CONVERT
), mp
->m_alloc_mnr
[0],
4187 mp
->m_alloc_mxr
[0], seqno
, bno
);
4191 rp
= XFS_BTREE_REC_ADDR(mp
->m_sb
.sb_blocksize
, xfs_alloc
, block
,
4192 1, mp
->m_alloc_mxr
[0]);
4193 for (i
= 0; i
< INT_GET(block
->bb_numrecs
, ARCH_CONVERT
); i
++) {
4194 set_dbmap(seqno
, INT_GET(rp
[i
].ar_startblock
, ARCH_CONVERT
),
4195 INT_GET(rp
[i
].ar_blockcount
, ARCH_CONVERT
), DBM_FREE1
,
4200 if (INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) > mp
->m_alloc_mxr
[1] ||
4201 (isroot
== 0 && INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) < mp
->m_alloc_mnr
[1])) {
4202 dbprintf("bad btree nrecs (%u, min=%u, max=%u) in btbno block "
4204 INT_GET(block
->bb_numrecs
, ARCH_CONVERT
), mp
->m_alloc_mnr
[1],
4205 mp
->m_alloc_mxr
[1], seqno
, bno
);
4209 pp
= XFS_BTREE_PTR_ADDR(mp
->m_sb
.sb_blocksize
, xfs_alloc
, block
, 1,
4210 mp
->m_alloc_mxr
[1]);
4211 for (i
= 0; i
< INT_GET(block
->bb_numrecs
, ARCH_CONVERT
); i
++)
4212 scan_sbtree(agf
, INT_GET(pp
[i
], ARCH_CONVERT
), level
, 0, scanfunc_bno
, TYP_BNOBT
);
4217 xfs_btree_sblock_t
*ablock
,
4223 xfs_alloc_block_t
*block
= (xfs_alloc_block_t
*)ablock
;
4224 xfs_agnumber_t seqno
= INT_GET(agf
->agf_seqno
, ARCH_CONVERT
);
4226 xfs_alloc_ptr_t
*pp
;
4227 xfs_alloc_rec_t
*rp
;
4229 if (INT_GET(block
->bb_magic
, ARCH_CONVERT
) != XFS_ABTC_MAGIC
) {
4230 dbprintf("bad magic # %#x in btcnt block %u/%u\n",
4231 INT_GET(block
->bb_magic
, ARCH_CONVERT
), seqno
, bno
);
4236 if (INT_GET(block
->bb_level
, ARCH_CONVERT
) != level
) {
4238 dbprintf("expected level %d got %d in btcnt block "
4240 level
, INT_GET(block
->bb_level
, ARCH_CONVERT
), seqno
, bno
);
4243 set_dbmap(seqno
, bno
, 1, DBM_BTCNT
, seqno
, bno
);
4245 if (INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) > mp
->m_alloc_mxr
[0] ||
4246 (isroot
== 0 && INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) < mp
->m_alloc_mnr
[0])) {
4247 dbprintf("bad btree nrecs (%u, min=%u, max=%u) in "
4248 "btbno block %u/%u\n",
4249 INT_GET(block
->bb_numrecs
, ARCH_CONVERT
), mp
->m_alloc_mnr
[0],
4250 mp
->m_alloc_mxr
[0], seqno
, bno
);
4254 rp
= XFS_BTREE_REC_ADDR(mp
->m_sb
.sb_blocksize
, xfs_alloc
, block
,
4255 1, mp
->m_alloc_mxr
[0]);
4256 for (i
= 0; i
< INT_GET(block
->bb_numrecs
, ARCH_CONVERT
); i
++) {
4257 check_set_dbmap(seqno
, INT_GET(rp
[i
].ar_startblock
, ARCH_CONVERT
),
4258 INT_GET(rp
[i
].ar_blockcount
, ARCH_CONVERT
), DBM_FREE1
, DBM_FREE2
,
4260 fdblocks
+= INT_GET(rp
[i
].ar_blockcount
, ARCH_CONVERT
);
4261 agffreeblks
+= INT_GET(rp
[i
].ar_blockcount
, ARCH_CONVERT
);
4262 if (INT_GET(rp
[i
].ar_blockcount
, ARCH_CONVERT
) > agflongest
)
4263 agflongest
= INT_GET(rp
[i
].ar_blockcount
, ARCH_CONVERT
);
4267 if (INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) > mp
->m_alloc_mxr
[1] ||
4268 (isroot
== 0 && INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) < mp
->m_alloc_mnr
[1])) {
4269 dbprintf("bad btree nrecs (%u, min=%u, max=%u) in btbno block "
4271 INT_GET(block
->bb_numrecs
, ARCH_CONVERT
), mp
->m_alloc_mnr
[1],
4272 mp
->m_alloc_mxr
[1], seqno
, bno
);
4276 pp
= XFS_BTREE_PTR_ADDR(mp
->m_sb
.sb_blocksize
, xfs_alloc
, block
, 1,
4277 mp
->m_alloc_mxr
[1]);
4278 for (i
= 0; i
< INT_GET(block
->bb_numrecs
, ARCH_CONVERT
); i
++)
4279 scan_sbtree(agf
, INT_GET(pp
[i
], ARCH_CONVERT
), level
, 0, scanfunc_cnt
, TYP_CNTBT
);
4284 xfs_btree_sblock_t
*ablock
,
4291 xfs_inobt_block_t
*block
= (xfs_inobt_block_t
*)ablock
;
4292 xfs_agnumber_t seqno
= INT_GET(agf
->agf_seqno
, ARCH_CONVERT
);
4298 xfs_inobt_ptr_t
*pp
;
4299 xfs_inobt_rec_t
*rp
;
4301 if (INT_GET(block
->bb_magic
, ARCH_CONVERT
) != XFS_IBT_MAGIC
) {
4302 dbprintf("bad magic # %#x in inobt block %u/%u\n",
4303 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 inobt block "
4311 level
, INT_GET(block
->bb_level
, ARCH_CONVERT
), seqno
, bno
);
4314 set_dbmap(seqno
, bno
, 1, DBM_BTINO
, seqno
, bno
);
4316 if (INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) > mp
->m_inobt_mxr
[0] ||
4317 (isroot
== 0 && INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) < mp
->m_inobt_mnr
[0])) {
4318 dbprintf("bad btree nrecs (%u, min=%u, max=%u) in "
4319 "inobt block %u/%u\n",
4320 INT_GET(block
->bb_numrecs
, ARCH_CONVERT
), mp
->m_inobt_mnr
[0],
4321 mp
->m_inobt_mxr
[0], seqno
, bno
);
4325 rp
= XFS_BTREE_REC_ADDR(mp
->m_sb
.sb_blocksize
, xfs_inobt
, block
,
4326 1, mp
->m_inobt_mxr
[0]);
4327 for (i
= 0; i
< INT_GET(block
->bb_numrecs
, ARCH_CONVERT
); i
++) {
4328 agino
= INT_GET(rp
[i
].ir_startino
, ARCH_CONVERT
);
4329 off
= XFS_INO_TO_OFFSET(mp
, agino
);
4331 if ((sbversion
& XFS_SB_VERSION_ALIGNBIT
) &&
4332 mp
->m_sb
.sb_inoalignmt
&&
4333 (XFS_INO_TO_AGBNO(mp
, agino
) %
4334 mp
->m_sb
.sb_inoalignmt
))
4335 sbversion
&= ~XFS_SB_VERSION_ALIGNBIT
;
4336 set_dbmap(seqno
, XFS_AGINO_TO_AGBNO(mp
, agino
),
4337 (xfs_extlen_t
)MAX(1,
4338 XFS_INODES_PER_CHUNK
>>
4339 mp
->m_sb
.sb_inopblog
),
4340 DBM_INODE
, seqno
, bno
);
4342 icount
+= XFS_INODES_PER_CHUNK
;
4343 agicount
+= XFS_INODES_PER_CHUNK
;
4344 ifree
+= INT_GET(rp
[i
].ir_freecount
, ARCH_CONVERT
);
4345 agifreecount
+= INT_GET(rp
[i
].ir_freecount
, ARCH_CONVERT
);
4347 set_cur(&typtab
[TYP_INODE
],
4348 XFS_AGB_TO_DADDR(mp
, seqno
,
4349 XFS_AGINO_TO_AGBNO(mp
, agino
)),
4350 (int)XFS_FSB_TO_BB(mp
, XFS_IALLOC_BLOCKS(mp
)),
4352 if (iocur_top
->data
== NULL
) {
4354 dbprintf("can't read inode block "
4357 XFS_AGINO_TO_AGBNO(mp
, agino
));
4361 for (j
= 0, nfree
= 0; j
< XFS_INODES_PER_CHUNK
; j
++) {
4362 if ((isfree
= XFS_INOBT_IS_FREE(&rp
[i
], j
, ARCH_CONVERT
)))
4364 process_inode(agf
, agino
+ j
,
4365 (xfs_dinode_t
*)((char *)iocur_top
->data
+ ((off
+ j
) << mp
->m_sb
.sb_inodelog
)),
4368 if (nfree
!= INT_GET(rp
[i
].ir_freecount
, ARCH_CONVERT
)) {
4370 dbprintf("ir_freecount/free mismatch, "
4371 "inode chunk %u/%u, freecount "
4374 INT_GET(rp
[i
].ir_freecount
, ARCH_CONVERT
), nfree
);
4381 if (INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) > mp
->m_inobt_mxr
[1] ||
4382 (isroot
== 0 && INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) < mp
->m_inobt_mnr
[1])) {
4383 dbprintf("bad btree nrecs (%u, min=%u, max=%u) in inobt block "
4385 INT_GET(block
->bb_numrecs
, ARCH_CONVERT
), mp
->m_inobt_mnr
[1],
4386 mp
->m_inobt_mxr
[1], seqno
, bno
);
4390 pp
= XFS_BTREE_PTR_ADDR(mp
->m_sb
.sb_blocksize
, xfs_inobt
, block
, 1,
4391 mp
->m_inobt_mxr
[1]);
4392 for (i
= 0; i
< INT_GET(block
->bb_numrecs
, ARCH_CONVERT
); i
++)
4393 scan_sbtree(agf
, INT_GET(pp
[i
], ARCH_CONVERT
), level
, 0, scanfunc_ino
, TYP_INOBT
);
4398 xfs_agnumber_t agno
,
4399 xfs_agblock_t agbno
,
4402 xfs_agnumber_t c_agno
,
4403 xfs_agblock_t c_agbno
)
4405 check_set_dbmap(agno
, agbno
, len
, DBM_UNKNOWN
, type
, c_agno
, c_agbno
);
4410 xfs_agnumber_t agno
,
4411 xfs_agblock_t agbno
,
4419 if (!check_inomap(agno
, agbno
, len
, id
->ino
))
4421 mayprint
= verbose
| id
->ilist
| blist_size
;
4422 for (i
= 0, idp
= &inomap
[agno
][agbno
]; i
< len
; i
++, idp
++) {
4425 (verbose
|| id
->ilist
|| CHECK_BLISTA(agno
, agbno
+ i
)))
4426 dbprintf("setting inode to %lld for block %u/%u\n",
4427 id
->ino
, agno
, agbno
+ i
);
4437 check_set_rdbmap(bno
, len
, DBM_UNKNOWN
, type
);
4450 if (!check_rinomap(bno
, len
, id
->ino
))
4452 mayprint
= verbose
| id
->ilist
| blist_size
;
4453 for (i
= 0, idp
= &inomap
[mp
->m_sb
.sb_agcount
][bno
];
4457 if (mayprint
&& (verbose
|| id
->ilist
|| CHECK_BLIST(bno
+ i
)))
4458 dbprintf("setting inode to %lld for rtblock %llu\n",
4470 id
->link_set
= nlink
;
4472 id
->security
= security
;
4473 if (verbose
|| id
->ilist
)
4474 dbprintf("inode %lld nlink %u %s dir\n", id
->ino
, nlink
,
4475 isdir
? "is" : "not");