]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - db/freesp.c
2 * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
28 typedef struct histent
36 static void addhistent(int h
);
37 static void addtohist(xfs_agnumber_t agno
, xfs_agblock_t agbno
,
39 static int freesp_f(int argc
, char **argv
);
40 static void histinit(int maxlen
);
41 static int init(int argc
, char **argv
);
42 static void printhist(void);
43 static void scan_ag(xfs_agnumber_t agno
);
44 static void scanfunc_bno(struct xfs_btree_block
*block
, typnm_t typ
, int level
,
46 static void scanfunc_cnt(struct xfs_btree_block
*block
, typnm_t typ
, int level
,
48 static void scan_freelist(xfs_agf_t
*agf
);
49 static void scan_sbtree(xfs_agf_t
*agf
, xfs_agblock_t root
, typnm_t typ
,
51 void (*func
)(struct xfs_btree_block
*block
, typnm_t typ
,
52 int level
, xfs_agf_t
*agf
));
53 static int usage(void);
56 static xfs_agnumber_t
*aglist
;
60 static histent_t
*hist
;
64 static int summaryflag
;
65 static long long totblocks
;
66 static long long totexts
;
68 static const cmdinfo_t freesp_cmd
=
69 { "freesp", NULL
, freesp_f
, 0, -1, 0,
70 "[-bcdfs] [-a agno]... [-e binsize] [-h h1]... [-m binmult]",
71 "summarize free space for filesystem", NULL
};
81 for (i
= 0; i
< agcount
; i
++)
82 if (aglist
[i
] == agno
)
88 * Report on freespace usage in xfs filesystem.
97 if (!init(argc
, argv
))
101 dbprintf("%8s %8s %8s\n", "agno", "agbno", "len");
103 for (agno
= 0; agno
< mp
->m_sb
.sb_agcount
; agno
++) {
110 dbprintf(_("total free extents %lld\n"), totexts
);
111 dbprintf(_("total free blocks %lld\n"), totblocks
);
112 dbprintf(_("average free extent size %g\n"),
113 (double)totblocks
/ (double)totexts
);
125 add_command(&freesp_cmd
);
132 aglist
= xrealloc(aglist
, (agcount
+ 1) * sizeof(*aglist
));
133 aglist
[agcount
] = (xfs_agnumber_t
)atoi(a
);
145 agcount
= countflag
= dumpflag
= equalsize
= multsize
= optind
= 0;
146 histcount
= seen1
= summaryflag
= 0;
147 totblocks
= totexts
= 0;
150 while ((c
= getopt(argc
, argv
, "a:bcde:h:m:s")) != EOF
) {
170 equalsize
= atoi(optarg
);
174 if (speced
&& !histcount
)
176 addhistent(atoi(optarg
));
182 multsize
= atoi(optarg
);
196 histinit((int)mp
->m_sb
.sb_agblocks
);
203 dbprintf(_("freesp arguments: [-bcds] [-a agno] [-e binsize] [-h h1]... "
215 set_cur(&typtab
[TYP_AGF
], XFS_AG_DADDR(mp
, agno
, XFS_AGF_DADDR(mp
)),
216 XFS_FSS_TO_BB(mp
, 1), DB_RING_IGN
, NULL
);
217 agf
= iocur_top
->data
;
220 scan_sbtree(agf
, be32_to_cpu(agf
->agf_roots
[XFS_BTNUM_CNT
]),
221 TYP_CNTBT
, be32_to_cpu(agf
->agf_levels
[XFS_BTNUM_CNT
]),
224 scan_sbtree(agf
, be32_to_cpu(agf
->agf_roots
[XFS_BTNUM_BNO
]),
225 TYP_BNOBT
, be32_to_cpu(agf
->agf_levels
[XFS_BTNUM_BNO
]),
234 xfs_agnumber_t seqno
= be32_to_cpu(agf
->agf_seqno
);
240 if (be32_to_cpu(agf
->agf_flcount
) == 0)
243 set_cur(&typtab
[TYP_AGFL
], XFS_AG_DADDR(mp
, seqno
, XFS_AGFL_DADDR(mp
)),
244 XFS_FSS_TO_BB(mp
, 1), DB_RING_IGN
, NULL
);
245 agfl
= iocur_top
->data
;
246 i
= be32_to_cpu(agf
->agf_flfirst
);
248 /* open coded XFS_BUF_TO_AGFL_BNO */
249 agfl_bno
= xfs_sb_version_hascrc(&mp
->m_sb
) ? &agfl
->agfl_bno
[0]
252 /* verify agf values before proceeding */
253 if (be32_to_cpu(agf
->agf_flfirst
) >= XFS_AGFL_SIZE(mp
) ||
254 be32_to_cpu(agf
->agf_fllast
) >= XFS_AGFL_SIZE(mp
)) {
255 dbprintf(_("agf %d freelist blocks bad, skipping "
256 "freelist scan\n"), i
);
262 bno
= be32_to_cpu(agfl_bno
[i
]);
263 addtohist(seqno
, bno
, 1);
264 if (i
== be32_to_cpu(agf
->agf_fllast
))
266 if (++i
== XFS_AGFL_SIZE(mp
))
278 void (*func
)(struct xfs_btree_block
*block
,
283 xfs_agnumber_t seqno
= be32_to_cpu(agf
->agf_seqno
);
286 set_cur(&typtab
[typ
], XFS_AGB_TO_DADDR(mp
, seqno
, root
),
287 blkbb
, DB_RING_IGN
, NULL
);
288 if (iocur_top
->data
== NULL
) {
289 dbprintf(_("can't read btree block %u/%u\n"), seqno
, root
);
292 (*func
)(iocur_top
->data
, typ
, nlevels
- 1, agf
);
299 struct xfs_btree_block
*block
,
308 if (!(be32_to_cpu(block
->bb_magic
) == XFS_ABTB_MAGIC
||
309 be32_to_cpu(block
->bb_magic
) == XFS_ABTB_CRC_MAGIC
))
313 rp
= XFS_ALLOC_REC_ADDR(mp
, block
, 1);
314 for (i
= 0; i
< be16_to_cpu(block
->bb_numrecs
); i
++)
315 addtohist(be32_to_cpu(agf
->agf_seqno
),
316 be32_to_cpu(rp
[i
].ar_startblock
),
317 be32_to_cpu(rp
[i
].ar_blockcount
));
320 pp
= XFS_ALLOC_PTR_ADDR(mp
, block
, 1, mp
->m_alloc_mxr
[1]);
321 for (i
= 0; i
< be16_to_cpu(block
->bb_numrecs
); i
++)
322 scan_sbtree(agf
, be32_to_cpu(pp
[i
]), typ
, level
, scanfunc_bno
);
327 struct xfs_btree_block
*block
,
336 if (!(be32_to_cpu(block
->bb_magic
) == XFS_ABTC_MAGIC
||
337 be32_to_cpu(block
->bb_magic
) == XFS_ABTC_CRC_MAGIC
))
341 rp
= XFS_ALLOC_REC_ADDR(mp
, block
, 1);
342 for (i
= 0; i
< be16_to_cpu(block
->bb_numrecs
); i
++)
343 addtohist(be32_to_cpu(agf
->agf_seqno
),
344 be32_to_cpu(rp
[i
].ar_startblock
),
345 be32_to_cpu(rp
[i
].ar_blockcount
));
348 pp
= XFS_ALLOC_PTR_ADDR(mp
, block
, 1, mp
->m_alloc_mxr
[1]);
349 for (i
= 0; i
< be16_to_cpu(block
->bb_numrecs
); i
++)
350 scan_sbtree(agf
, be32_to_cpu(pp
[i
]), typ
, level
, scanfunc_cnt
);
357 hist
= xrealloc(hist
, (histcount
+ 1) * sizeof(*hist
));
360 hist
[histcount
].low
= h
;
361 hist
[histcount
].count
= hist
[histcount
].blocks
= 0;
376 dbprintf("%8d %8d %8d\n", agno
, agbno
, len
);
379 for (i
= 0; i
< histcount
; i
++) {
380 if (hist
[i
].high
>= len
) {
382 hist
[i
].blocks
+= len
;
393 return ((histent_t
*)a
)->low
- ((histent_t
*)b
)->low
;
403 for (i
= 1; i
< maxlen
; i
+= equalsize
)
405 } else if (multsize
) {
406 for (i
= 1; i
< maxlen
; i
*= multsize
)
411 qsort(hist
, histcount
, sizeof(*hist
), hcmp
);
413 for (i
= 0; i
< histcount
; i
++) {
414 if (i
< histcount
- 1)
415 hist
[i
].high
= hist
[i
+ 1].low
- 1;
417 hist
[i
].high
= maxlen
;
426 dbprintf("%7s %7s %7s %7s %6s\n",
427 _("from"), _("to"), _("extents"), _("blocks"), _("pct"));
428 for (i
= 0; i
< histcount
; i
++) {
430 dbprintf("%7d %7d %7lld %7lld %6.2f\n", hist
[i
].low
,
431 hist
[i
].high
, hist
[i
].count
, hist
[i
].blocks
,
432 hist
[i
].blocks
* 100.0 / totblocks
);