]>
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
;
61 static histent_t
*hist
;
65 static int summaryflag
;
66 static long long totblocks
;
67 static long long totexts
;
69 static const cmdinfo_t freesp_cmd
=
70 { "freesp", NULL
, freesp_f
, 0, -1, 0,
71 "[-bcdfs] [-A alignment] [-a agno]... [-e binsize] [-h h1]... [-m binmult]",
72 "summarize free space for filesystem", NULL
};
82 for (i
= 0; i
< agcount
; i
++)
83 if (aglist
[i
] == agno
)
89 * Report on freespace usage in xfs filesystem.
98 if (!init(argc
, argv
))
102 dbprintf("%8s %8s %8s\n", "agno", "agbno", "len");
104 for (agno
= 0; agno
< mp
->m_sb
.sb_agcount
; agno
++) {
111 dbprintf(_("total free extents %lld\n"), totexts
);
112 dbprintf(_("total free blocks %lld\n"), totblocks
);
113 dbprintf(_("average free extent size %g\n"),
114 (double)totblocks
/ (double)totexts
);
126 add_command(&freesp_cmd
);
133 aglist
= xrealloc(aglist
, (agcount
+ 1) * sizeof(*aglist
));
134 aglist
[agcount
] = (xfs_agnumber_t
)atoi(a
);
146 agcount
= countflag
= dumpflag
= equalsize
= multsize
= optind
= 0;
147 histcount
= seen1
= summaryflag
= 0;
148 totblocks
= totexts
= 0;
151 while ((c
= getopt(argc
, argv
, "A:a:bcde:h:m:s")) != EOF
) {
154 alignment
= atoi(optarg
);
174 equalsize
= atoi(optarg
);
178 if (speced
&& !histcount
)
180 addhistent(atoi(optarg
));
186 multsize
= atoi(optarg
);
200 histinit((int)mp
->m_sb
.sb_agblocks
);
207 dbprintf(_("freesp arguments: [-bcds] [-a agno] [-e binsize] [-h h1]... "
219 set_cur(&typtab
[TYP_AGF
], XFS_AG_DADDR(mp
, agno
, XFS_AGF_DADDR(mp
)),
220 XFS_FSS_TO_BB(mp
, 1), DB_RING_IGN
, NULL
);
221 agf
= iocur_top
->data
;
224 scan_sbtree(agf
, be32_to_cpu(agf
->agf_roots
[XFS_BTNUM_CNT
]),
225 TYP_CNTBT
, be32_to_cpu(agf
->agf_levels
[XFS_BTNUM_CNT
]),
228 scan_sbtree(agf
, be32_to_cpu(agf
->agf_roots
[XFS_BTNUM_BNO
]),
229 TYP_BNOBT
, be32_to_cpu(agf
->agf_levels
[XFS_BTNUM_BNO
]),
238 xfs_agnumber_t seqno
= be32_to_cpu(agf
->agf_seqno
);
244 if (be32_to_cpu(agf
->agf_flcount
) == 0)
247 set_cur(&typtab
[TYP_AGFL
], XFS_AG_DADDR(mp
, seqno
, XFS_AGFL_DADDR(mp
)),
248 XFS_FSS_TO_BB(mp
, 1), DB_RING_IGN
, NULL
);
249 agfl
= iocur_top
->data
;
250 i
= be32_to_cpu(agf
->agf_flfirst
);
252 /* open coded XFS_BUF_TO_AGFL_BNO */
253 agfl_bno
= xfs_sb_version_hascrc(&mp
->m_sb
) ? &agfl
->agfl_bno
[0]
256 /* verify agf values before proceeding */
257 if (be32_to_cpu(agf
->agf_flfirst
) >= XFS_AGFL_SIZE(mp
) ||
258 be32_to_cpu(agf
->agf_fllast
) >= XFS_AGFL_SIZE(mp
)) {
259 dbprintf(_("agf %d freelist blocks bad, skipping "
260 "freelist scan\n"), i
);
266 bno
= be32_to_cpu(agfl_bno
[i
]);
267 addtohist(seqno
, bno
, 1);
268 if (i
== be32_to_cpu(agf
->agf_fllast
))
270 if (++i
== XFS_AGFL_SIZE(mp
))
282 void (*func
)(struct xfs_btree_block
*block
,
287 xfs_agnumber_t seqno
= be32_to_cpu(agf
->agf_seqno
);
290 set_cur(&typtab
[typ
], XFS_AGB_TO_DADDR(mp
, seqno
, root
),
291 blkbb
, DB_RING_IGN
, NULL
);
292 if (iocur_top
->data
== NULL
) {
293 dbprintf(_("can't read btree block %u/%u\n"), seqno
, root
);
296 (*func
)(iocur_top
->data
, typ
, nlevels
- 1, agf
);
303 struct xfs_btree_block
*block
,
312 if (!(be32_to_cpu(block
->bb_magic
) == XFS_ABTB_MAGIC
||
313 be32_to_cpu(block
->bb_magic
) == XFS_ABTB_CRC_MAGIC
))
317 rp
= XFS_ALLOC_REC_ADDR(mp
, block
, 1);
318 for (i
= 0; i
< be16_to_cpu(block
->bb_numrecs
); i
++)
319 addtohist(be32_to_cpu(agf
->agf_seqno
),
320 be32_to_cpu(rp
[i
].ar_startblock
),
321 be32_to_cpu(rp
[i
].ar_blockcount
));
324 pp
= XFS_ALLOC_PTR_ADDR(mp
, block
, 1, mp
->m_alloc_mxr
[1]);
325 for (i
= 0; i
< be16_to_cpu(block
->bb_numrecs
); i
++)
326 scan_sbtree(agf
, be32_to_cpu(pp
[i
]), typ
, level
, scanfunc_bno
);
331 struct xfs_btree_block
*block
,
340 if (!(be32_to_cpu(block
->bb_magic
) == XFS_ABTC_MAGIC
||
341 be32_to_cpu(block
->bb_magic
) == XFS_ABTC_CRC_MAGIC
))
345 rp
= XFS_ALLOC_REC_ADDR(mp
, block
, 1);
346 for (i
= 0; i
< be16_to_cpu(block
->bb_numrecs
); i
++)
347 addtohist(be32_to_cpu(agf
->agf_seqno
),
348 be32_to_cpu(rp
[i
].ar_startblock
),
349 be32_to_cpu(rp
[i
].ar_blockcount
));
352 pp
= XFS_ALLOC_PTR_ADDR(mp
, block
, 1, mp
->m_alloc_mxr
[1]);
353 for (i
= 0; i
< be16_to_cpu(block
->bb_numrecs
); i
++)
354 scan_sbtree(agf
, be32_to_cpu(pp
[i
]), typ
, level
, scanfunc_cnt
);
361 hist
= xrealloc(hist
, (histcount
+ 1) * sizeof(*hist
));
364 hist
[histcount
].low
= h
;
365 hist
[histcount
].count
= hist
[histcount
].blocks
= 0;
379 if (alignment
&& (XFS_AGB_TO_FSB(mp
,agno
,agbno
) % alignment
))
383 dbprintf("%8d %8d %8d\n", agno
, agbno
, len
);
386 for (i
= 0; i
< histcount
; i
++) {
387 if (hist
[i
].high
>= len
) {
389 hist
[i
].blocks
+= len
;
400 return ((histent_t
*)a
)->low
- ((histent_t
*)b
)->low
;
410 for (i
= 1; i
< maxlen
; i
+= equalsize
)
412 } else if (multsize
) {
413 for (i
= 1; i
< maxlen
; i
*= multsize
)
418 qsort(hist
, histcount
, sizeof(*hist
), hcmp
);
420 for (i
= 0; i
< histcount
; i
++) {
421 if (i
< histcount
- 1)
422 hist
[i
].high
= hist
[i
+ 1].low
- 1;
424 hist
[i
].high
= maxlen
;
433 dbprintf("%7s %7s %7s %7s %6s\n",
434 _("from"), _("to"), _("extents"), _("blocks"), _("pct"));
435 for (i
= 0; i
< histcount
; i
++) {
437 dbprintf("%7d %7d %7lld %7lld %6.2f\n", hist
[i
].low
,
438 hist
[i
].high
, hist
[i
].count
, hist
[i
].blocks
,
439 hist
[i
].blocks
* 100.0 / totblocks
);