]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - db/freesp.c
1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
16 typedef struct histent
24 static void addhistent(int h
);
25 static void addtohist(xfs_agnumber_t agno
, xfs_agblock_t agbno
,
27 static int freesp_f(int argc
, char **argv
);
28 static void histinit(int maxlen
);
29 static int init(int argc
, char **argv
);
30 static void printhist(void);
31 static void scan_ag(xfs_agnumber_t agno
);
32 static void scanfunc_bno(struct xfs_btree_block
*block
, typnm_t typ
, int level
,
34 static void scanfunc_cnt(struct xfs_btree_block
*block
, typnm_t typ
, int level
,
36 static void scan_freelist(xfs_agf_t
*agf
);
37 static void scan_sbtree(xfs_agf_t
*agf
, xfs_agblock_t root
, typnm_t typ
,
39 void (*func
)(struct xfs_btree_block
*block
, typnm_t typ
,
40 int level
, xfs_agf_t
*agf
));
41 static int usage(void);
44 static xfs_agnumber_t
*aglist
;
49 static histent_t
*hist
;
53 static int summaryflag
;
54 static long long totblocks
;
55 static long long totexts
;
57 static const cmdinfo_t freesp_cmd
=
58 { "freesp", NULL
, freesp_f
, 0, -1, 0,
59 "[-bcdfs] [-A alignment] [-a agno]... [-e binsize] [-h h1]... [-m binmult]",
60 "summarize free space for filesystem", NULL
};
70 for (i
= 0; i
< agcount
; i
++)
71 if (aglist
[i
] == agno
)
77 * Report on freespace usage in xfs filesystem.
86 if (!init(argc
, argv
))
90 dbprintf("%8s %8s %8s\n", "agno", "agbno", "len");
92 for (agno
= 0; agno
< mp
->m_sb
.sb_agcount
; agno
++) {
99 dbprintf(_("total free extents %lld\n"), totexts
);
100 dbprintf(_("total free blocks %lld\n"), totblocks
);
101 dbprintf(_("average free extent size %g\n"),
102 (double)totblocks
/ (double)totexts
);
114 add_command(&freesp_cmd
);
121 aglist
= xrealloc(aglist
, (agcount
+ 1) * sizeof(*aglist
));
122 aglist
[agcount
] = (xfs_agnumber_t
)atoi(a
);
134 agcount
= countflag
= dumpflag
= equalsize
= multsize
= optind
= 0;
135 histcount
= seen1
= summaryflag
= 0;
136 totblocks
= totexts
= 0;
139 while ((c
= getopt(argc
, argv
, "A:a:bcde:h:m:s")) != EOF
) {
142 alignment
= atoi(optarg
);
162 equalsize
= atoi(optarg
);
166 if (speced
&& !histcount
)
168 addhistent(atoi(optarg
));
174 multsize
= atoi(optarg
);
188 histinit((int)mp
->m_sb
.sb_agblocks
);
195 dbprintf(_("freesp arguments: [-bcds] [-a agno] [-e binsize] [-h h1]... "
207 set_cur(&typtab
[TYP_AGF
], XFS_AG_DADDR(mp
, agno
, XFS_AGF_DADDR(mp
)),
208 XFS_FSS_TO_BB(mp
, 1), DB_RING_IGN
, NULL
);
209 agf
= iocur_top
->data
;
212 scan_sbtree(agf
, be32_to_cpu(agf
->agf_roots
[XFS_BTNUM_CNT
]),
213 TYP_CNTBT
, be32_to_cpu(agf
->agf_levels
[XFS_BTNUM_CNT
]),
216 scan_sbtree(agf
, be32_to_cpu(agf
->agf_roots
[XFS_BTNUM_BNO
]),
217 TYP_BNOBT
, be32_to_cpu(agf
->agf_levels
[XFS_BTNUM_BNO
]),
224 struct xfs_mount
*mp
,
228 addtohist(*(xfs_agnumber_t
*)priv
, bno
, 1);
236 xfs_agnumber_t seqno
= be32_to_cpu(agf
->agf_seqno
);
238 if (be32_to_cpu(agf
->agf_flcount
) == 0)
241 set_cur(&typtab
[TYP_AGFL
], XFS_AG_DADDR(mp
, seqno
, XFS_AGFL_DADDR(mp
)),
242 XFS_FSS_TO_BB(mp
, 1), DB_RING_IGN
, NULL
);
244 /* verify agf values before proceeding */
245 if (be32_to_cpu(agf
->agf_flfirst
) >= libxfs_agfl_size(mp
) ||
246 be32_to_cpu(agf
->agf_fllast
) >= libxfs_agfl_size(mp
)) {
247 dbprintf(_("agf %d freelist blocks bad, skipping "
248 "freelist scan\n"), seqno
);
253 libxfs_agfl_walk(mp
, agf
, iocur_top
->bp
, scan_agfl
, &seqno
);
263 void (*func
)(struct xfs_btree_block
*block
,
268 xfs_agnumber_t seqno
= be32_to_cpu(agf
->agf_seqno
);
271 set_cur(&typtab
[typ
], XFS_AGB_TO_DADDR(mp
, seqno
, root
),
272 blkbb
, DB_RING_IGN
, NULL
);
273 if (iocur_top
->data
== NULL
) {
274 dbprintf(_("can't read btree block %u/%u\n"), seqno
, root
);
277 (*func
)(iocur_top
->data
, typ
, nlevels
- 1, agf
);
284 struct xfs_btree_block
*block
,
293 if (!(be32_to_cpu(block
->bb_magic
) == XFS_ABTB_MAGIC
||
294 be32_to_cpu(block
->bb_magic
) == XFS_ABTB_CRC_MAGIC
))
298 rp
= XFS_ALLOC_REC_ADDR(mp
, block
, 1);
299 for (i
= 0; i
< be16_to_cpu(block
->bb_numrecs
); i
++)
300 addtohist(be32_to_cpu(agf
->agf_seqno
),
301 be32_to_cpu(rp
[i
].ar_startblock
),
302 be32_to_cpu(rp
[i
].ar_blockcount
));
305 pp
= XFS_ALLOC_PTR_ADDR(mp
, block
, 1, mp
->m_alloc_mxr
[1]);
306 for (i
= 0; i
< be16_to_cpu(block
->bb_numrecs
); i
++)
307 scan_sbtree(agf
, be32_to_cpu(pp
[i
]), typ
, level
, scanfunc_bno
);
312 struct xfs_btree_block
*block
,
321 if (!(be32_to_cpu(block
->bb_magic
) == XFS_ABTC_MAGIC
||
322 be32_to_cpu(block
->bb_magic
) == XFS_ABTC_CRC_MAGIC
))
326 rp
= XFS_ALLOC_REC_ADDR(mp
, block
, 1);
327 for (i
= 0; i
< be16_to_cpu(block
->bb_numrecs
); i
++)
328 addtohist(be32_to_cpu(agf
->agf_seqno
),
329 be32_to_cpu(rp
[i
].ar_startblock
),
330 be32_to_cpu(rp
[i
].ar_blockcount
));
333 pp
= XFS_ALLOC_PTR_ADDR(mp
, block
, 1, mp
->m_alloc_mxr
[1]);
334 for (i
= 0; i
< be16_to_cpu(block
->bb_numrecs
); i
++)
335 scan_sbtree(agf
, be32_to_cpu(pp
[i
]), typ
, level
, scanfunc_cnt
);
342 hist
= xrealloc(hist
, (histcount
+ 1) * sizeof(*hist
));
345 hist
[histcount
].low
= h
;
346 hist
[histcount
].count
= hist
[histcount
].blocks
= 0;
360 if (alignment
&& (XFS_AGB_TO_FSB(mp
,agno
,agbno
) % alignment
))
364 dbprintf("%8d %8d %8d\n", agno
, agbno
, len
);
367 for (i
= 0; i
< histcount
; i
++) {
368 if (hist
[i
].high
>= len
) {
370 hist
[i
].blocks
+= len
;
381 return ((histent_t
*)a
)->low
- ((histent_t
*)b
)->low
;
391 for (i
= 1; i
< maxlen
; i
+= equalsize
)
393 } else if (multsize
) {
394 for (i
= 1; i
< maxlen
; i
*= multsize
)
399 qsort(hist
, histcount
, sizeof(*hist
), hcmp
);
401 for (i
= 0; i
< histcount
; i
++) {
402 if (i
< histcount
- 1)
403 hist
[i
].high
= hist
[i
+ 1].low
- 1;
405 hist
[i
].high
= maxlen
;
414 dbprintf("%7s %7s %7s %7s %6s\n",
415 _("from"), _("to"), _("extents"), _("blocks"), _("pct"));
416 for (i
= 0; i
< histcount
; i
++) {
418 dbprintf("%7d %7d %7lld %7lld %6.2f\n", hist
[i
].low
,
419 hist
[i
].high
, hist
[i
].count
, hist
[i
].blocks
,
420 hist
[i
].blocks
* 100.0 / totblocks
);