]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - db/freesp.c
7a6becfd4c5b049c3d20e225d2660cd47fab9003
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/
44 typedef struct histent
52 static void addhistent(int h
);
53 static void addtohist(xfs_agnumber_t agno
, xfs_agblock_t agbno
,
55 static int freesp_f(int argc
, char **argv
);
56 static void histinit(int maxlen
);
57 static int init(int argc
, char **argv
);
58 static void printhist(void);
59 static void scan_ag(xfs_agnumber_t agno
);
60 static void scanfunc_bno(xfs_btree_sblock_t
*ablock
, typnm_t typ
, int level
,
62 static void scanfunc_cnt(xfs_btree_sblock_t
*ablock
, typnm_t typ
, int level
,
64 static void scan_freelist(xfs_agf_t
*agf
);
65 static void scan_sbtree(xfs_agf_t
*agf
, xfs_agblock_t root
, typnm_t typ
,
67 void (*func
)(xfs_btree_sblock_t
*block
, typnm_t typ
,
68 int level
, xfs_agf_t
*agf
));
69 static int usage(void);
72 static xfs_agnumber_t
*aglist
;
76 static histent_t
*hist
;
80 static int summaryflag
;
81 static long long totblocks
;
82 static long long totexts
;
84 static const cmdinfo_t freesp_cmd
=
85 { "freesp", NULL
, freesp_f
, 0, -1, 0,
86 "[-bcdfs] [-a agno]... [-e binsize] [-h h1]... [-m binmult]",
87 "summarize free space for filesystem", NULL
};
97 for (i
= 0; i
< agcount
; i
++)
98 if (aglist
[i
] == agno
)
104 * Report on freespace usage in xfs filesystem.
113 if (!init(argc
, argv
))
115 for (agno
= 0; agno
< mp
->m_sb
.sb_agcount
; agno
++) {
122 dbprintf("total free extents %lld\n", totexts
);
123 dbprintf("total free blocks %lld\n", totblocks
);
124 dbprintf("average free extent size %g\n",
125 (double)totblocks
/ (double)totexts
);
137 add_command(&freesp_cmd
);
144 aglist
= xrealloc(aglist
, (agcount
+ 1) * sizeof(*aglist
));
145 aglist
[agcount
] = (xfs_agnumber_t
)atoi(a
);
157 agcount
= countflag
= dumpflag
= equalsize
= multsize
= optind
= 0;
158 histcount
= seen1
= summaryflag
= 0;
159 totblocks
= totexts
= 0;
162 while ((c
= getopt(argc
, argv
, "a:bcde:h:m:s")) != EOF
) {
182 equalsize
= atoi(optarg
);
186 if (speced
&& !histcount
)
188 addhistent(atoi(optarg
));
194 multsize
= atoi(optarg
);
208 histinit((int)mp
->m_sb
.sb_agblocks
);
215 dbprintf("freesp arguments: [-bcdfs] [-a agno] [-e binsize] [-h h1]... "
227 set_cur(&typtab
[TYP_AGF
], XFS_AG_DADDR(mp
, agno
, XFS_AGF_DADDR
), 1,
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
), 1,
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
)
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
), INT_GET(rp
[i
].ar_blockcount
, ARCH_CONVERT
));
319 pp
= XFS_BTREE_PTR_ADDR(mp
->m_sb
.sb_blocksize
, xfs_alloc
, block
, 1,
321 for (i
= 0; i
< INT_GET(block
->bb_numrecs
, ARCH_CONVERT
); i
++)
322 scan_sbtree(agf
, pp
[i
], typ
, level
, scanfunc_bno
);
327 xfs_btree_sblock_t
*ablock
,
332 xfs_alloc_block_t
*block
= (xfs_alloc_block_t
*)ablock
;
338 rp
= XFS_BTREE_REC_ADDR(mp
->m_sb
.sb_blocksize
, xfs_alloc
, block
,
339 1, mp
->m_alloc_mxr
[0]);
340 for (i
= 0; i
< INT_GET(block
->bb_numrecs
, ARCH_CONVERT
); i
++)
341 addtohist(INT_GET(agf
->agf_seqno
, ARCH_CONVERT
),
342 INT_GET(rp
[i
].ar_startblock
, ARCH_CONVERT
), INT_GET(rp
[i
].ar_blockcount
, ARCH_CONVERT
));
345 pp
= XFS_BTREE_PTR_ADDR(mp
->m_sb
.sb_blocksize
, xfs_alloc
, block
, 1,
347 for (i
= 0; i
< INT_GET(block
->bb_numrecs
, ARCH_CONVERT
); i
++)
348 scan_sbtree(agf
, pp
[i
], typ
, level
, scanfunc_cnt
);
355 hist
= xrealloc(hist
, (histcount
+ 1) * sizeof(*hist
));
358 hist
[histcount
].low
= h
;
359 hist
[histcount
].count
= hist
[histcount
].blocks
= 0;
374 dbprintf("%8d %8d %8d\n", agno
, agbno
, len
);
377 for (i
= 0; i
< histcount
; i
++) {
378 if (hist
[i
].high
>= len
) {
380 hist
[i
].blocks
+= len
;
391 return ((histent_t
*)a
)->low
- ((histent_t
*)b
)->low
;
401 for (i
= 1; i
< maxlen
; i
+= equalsize
)
403 } else if (multsize
) {
404 for (i
= 1; i
< maxlen
; i
*= multsize
)
409 qsort(hist
, histcount
, sizeof(*hist
), hcmp
);
411 for (i
= 0; i
< histcount
; i
++) {
412 if (i
< histcount
- 1)
413 hist
[i
].high
= hist
[i
+ 1].low
- 1;
415 hist
[i
].high
= maxlen
;
424 dbprintf("%7s %7s %7s %7s %6s\n",
425 "from", "to", "extents", "blocks", "pct");
426 for (i
= 0; i
< histcount
; i
++) {
428 dbprintf("%7d %7d %7lld %7lld %6.2f\n", hist
[i
].low
,
429 hist
[i
].high
, hist
[i
].count
, hist
[i
].blocks
,
430 hist
[i
].blocks
* 100.0 / totblocks
);