]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - db/freesp.c
2 * Copyright (c) 2000-2001 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/
43 typedef struct histent
51 static void addhistent(int h
);
52 static void addtohist(xfs_agnumber_t agno
, xfs_agblock_t agbno
,
54 static int freesp_f(int argc
, char **argv
);
55 static void histinit(int maxlen
);
56 static int init(int argc
, char **argv
);
57 static void printhist(void);
58 static void scan_ag(xfs_agnumber_t agno
);
59 static void scanfunc_bno(xfs_btree_sblock_t
*ablock
, typnm_t typ
, int level
,
61 static void scanfunc_cnt(xfs_btree_sblock_t
*ablock
, typnm_t typ
, int level
,
63 static void scan_freelist(xfs_agf_t
*agf
);
64 static void scan_sbtree(xfs_agf_t
*agf
, xfs_agblock_t root
, typnm_t typ
,
66 void (*func
)(xfs_btree_sblock_t
*block
, typnm_t typ
,
67 int level
, xfs_agf_t
*agf
));
68 static int usage(void);
71 static xfs_agnumber_t
*aglist
;
75 static histent_t
*hist
;
79 static int summaryflag
;
80 static long long totblocks
;
81 static long long totexts
;
83 static const cmdinfo_t freesp_cmd
=
84 { "freesp", NULL
, freesp_f
, 0, -1, 0,
85 "[-bcdfs] [-a agno]... [-e binsize] [-h h1]... [-m binmult]",
86 "summarize free space for filesystem", NULL
};
96 for (i
= 0; i
< agcount
; i
++)
97 if (aglist
[i
] == agno
)
103 * Report on freespace usage in xfs filesystem.
112 if (!init(argc
, argv
))
114 for (agno
= 0; agno
< mp
->m_sb
.sb_agcount
; agno
++) {
121 dbprintf("total free extents %lld\n", totexts
);
122 dbprintf("total free blocks %lld\n", totblocks
);
123 dbprintf("average free extent size %g\n",
124 (double)totblocks
/ (double)totexts
);
136 add_command(&freesp_cmd
);
143 aglist
= xrealloc(aglist
, (agcount
+ 1) * sizeof(*aglist
));
144 aglist
[agcount
] = (xfs_agnumber_t
)atoi(a
);
156 agcount
= countflag
= dumpflag
= equalsize
= multsize
= optind
= 0;
157 histcount
= seen1
= summaryflag
= 0;
158 totblocks
= totexts
= 0;
161 while ((c
= getopt(argc
, argv
, "a:bcde:h:m:s")) != EOF
) {
181 equalsize
= atoi(optarg
);
185 if (speced
&& !histcount
)
187 addhistent(atoi(optarg
));
193 multsize
= atoi(optarg
);
207 histinit((int)mp
->m_sb
.sb_agblocks
);
214 dbprintf("freesp arguments: [-bcdfs] [-a agno] [-e binsize] [-h h1]... "
226 set_cur(&typtab
[TYP_AGF
],
227 XFS_AG_DADDR(mp
, agno
, XFS_AGF_DADDR(mp
)),
228 XFS_FSS_TO_BB(mp
, 1), DB_RING_IGN
, NULL
);
229 agf
= iocur_top
->data
;
233 INT_GET(agf
->agf_roots
[XFS_BTNUM_CNT
], ARCH_CONVERT
),
235 INT_GET(agf
->agf_levels
[XFS_BTNUM_CNT
], ARCH_CONVERT
),
239 INT_GET(agf
->agf_roots
[XFS_BTNUM_BNO
], ARCH_CONVERT
),
241 INT_GET(agf
->agf_levels
[XFS_BTNUM_BNO
], ARCH_CONVERT
),
250 xfs_agnumber_t seqno
= INT_GET(agf
->agf_seqno
, ARCH_CONVERT
);
255 if (INT_GET(agf
->agf_flcount
, ARCH_CONVERT
) == 0)
258 set_cur(&typtab
[TYP_AGFL
],
259 XFS_AG_DADDR(mp
, seqno
, XFS_AGFL_DADDR(mp
)),
260 XFS_FSS_TO_BB(mp
, 1), DB_RING_IGN
, NULL
);
261 agfl
= iocur_top
->data
;
262 i
= INT_GET(agf
->agf_flfirst
, ARCH_CONVERT
);
264 bno
= INT_GET(agfl
->agfl_bno
[i
], ARCH_CONVERT
);
265 addtohist(seqno
, bno
, 1);
266 if (i
== INT_GET(agf
->agf_fllast
, ARCH_CONVERT
))
268 if (++i
== XFS_AGFL_SIZE(mp
))
280 void (*func
)(xfs_btree_sblock_t
*block
,
285 xfs_agnumber_t seqno
= INT_GET(agf
->agf_seqno
, ARCH_CONVERT
);
288 set_cur(&typtab
[typ
], XFS_AGB_TO_DADDR(mp
, seqno
, root
),
289 blkbb
, DB_RING_IGN
, NULL
);
290 if (iocur_top
->data
== NULL
) {
291 dbprintf("can't read btree block %u/%u\n", seqno
, root
);
294 (*func
)((xfs_btree_sblock_t
*)iocur_top
->data
, typ
, nlevels
- 1, agf
);
301 xfs_btree_sblock_t
*ablock
,
306 xfs_alloc_block_t
*block
= (xfs_alloc_block_t
*)ablock
;
312 rp
= XFS_BTREE_REC_ADDR(mp
->m_sb
.sb_blocksize
, xfs_alloc
, block
,
313 1, mp
->m_alloc_mxr
[0]);
314 for (i
= 0; i
< INT_GET(block
->bb_numrecs
, ARCH_CONVERT
); i
++)
315 addtohist(INT_GET(agf
->agf_seqno
, ARCH_CONVERT
),
316 INT_GET(rp
[i
].ar_startblock
, ARCH_CONVERT
),
317 INT_GET(rp
[i
].ar_blockcount
, ARCH_CONVERT
));
320 pp
= XFS_BTREE_PTR_ADDR(mp
->m_sb
.sb_blocksize
, xfs_alloc
, block
, 1,
322 for (i
= 0; i
< INT_GET(block
->bb_numrecs
, ARCH_CONVERT
); i
++)
323 scan_sbtree(agf
, INT_GET(pp
[i
], ARCH_CONVERT
), typ
, level
,
329 xfs_btree_sblock_t
*ablock
,
334 xfs_alloc_block_t
*block
= (xfs_alloc_block_t
*)ablock
;
340 rp
= XFS_BTREE_REC_ADDR(mp
->m_sb
.sb_blocksize
, xfs_alloc
, block
,
341 1, mp
->m_alloc_mxr
[0]);
342 for (i
= 0; i
< INT_GET(block
->bb_numrecs
, ARCH_CONVERT
); i
++)
343 addtohist(INT_GET(agf
->agf_seqno
, ARCH_CONVERT
),
344 INT_GET(rp
[i
].ar_startblock
, ARCH_CONVERT
),
345 INT_GET(rp
[i
].ar_blockcount
, ARCH_CONVERT
));
348 pp
= XFS_BTREE_PTR_ADDR(mp
->m_sb
.sb_blocksize
, xfs_alloc
, block
, 1,
350 for (i
= 0; i
< INT_GET(block
->bb_numrecs
, ARCH_CONVERT
); i
++)
351 scan_sbtree(agf
, INT_GET(pp
[i
], ARCH_CONVERT
), typ
, level
,
359 hist
= xrealloc(hist
, (histcount
+ 1) * sizeof(*hist
));
362 hist
[histcount
].low
= h
;
363 hist
[histcount
].count
= hist
[histcount
].blocks
= 0;
378 dbprintf("%8d %8d %8d\n", agno
, agbno
, len
);
381 for (i
= 0; i
< histcount
; i
++) {
382 if (hist
[i
].high
>= len
) {
384 hist
[i
].blocks
+= len
;
395 return ((histent_t
*)a
)->low
- ((histent_t
*)b
)->low
;
405 for (i
= 1; i
< maxlen
; i
+= equalsize
)
407 } else if (multsize
) {
408 for (i
= 1; i
< maxlen
; i
*= multsize
)
413 qsort(hist
, histcount
, sizeof(*hist
), hcmp
);
415 for (i
= 0; i
< histcount
; i
++) {
416 if (i
< histcount
- 1)
417 hist
[i
].high
= hist
[i
+ 1].low
- 1;
419 hist
[i
].high
= maxlen
;
428 dbprintf("%7s %7s %7s %7s %6s\n",
429 "from", "to", "extents", "blocks", "pct");
430 for (i
= 0; i
< histcount
; i
++) {
432 dbprintf("%7d %7d %7lld %7lld %6.2f\n", hist
[i
].low
,
433 hist
[i
].high
, hist
[i
].count
, hist
[i
].blocks
,
434 hist
[i
].blocks
* 100.0 / totblocks
);