]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - spaceman/freesp.c
1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
4 * Copyright (c) 2012 Red Hat, Inc.
5 * Copyright (c) 2017 Oracle.
10 #include <linux/fiemap.h>
11 #include "libfrog/fsgeom.h"
14 #include "libfrog/paths.h"
27 static xfs_agnumber_t
*aglist
;
28 static struct histent
*hist
;
30 static long long equalsize
;
31 static long long multsize
;
34 static int summaryflag
;
37 static long long totblocks
;
38 static long long totexts
;
40 static cmdinfo_t freesp_cmd
;
46 if (histcount
== INT_MAX
) {
47 printf(_("Too many histogram buckets.\n"));
50 hist
= realloc(hist
, (histcount
+ 1) * sizeof(*hist
));
53 hist
[histcount
].low
= h
;
54 hist
[histcount
].count
= hist
[histcount
].blocks
= 0;
69 printf("%8d %8d %8"PRId64
"\n", agno
, agbno
, len
);
72 for (i
= 0; i
< histcount
; i
++) {
73 if (hist
[i
].high
>= len
) {
75 hist
[i
].blocks
+= len
;
86 return ((struct histent
*)a
)->low
- ((struct histent
*)b
)->low
;
96 for (i
= 1; i
< maxlen
; i
+= equalsize
)
98 } else if (multsize
) {
99 for (i
= 1; i
< maxlen
; i
*= multsize
)
104 qsort(hist
, histcount
, sizeof(*hist
), hcmp
);
106 for (i
= 0; i
< histcount
; i
++) {
107 if (i
< histcount
- 1)
108 hist
[i
].high
= hist
[i
+ 1].low
- 1;
110 hist
[i
].high
= maxlen
;
119 printf("%7s %7s %7s %7s %6s\n",
120 _("from"), _("to"), _("extents"), _("blocks"), _("pct"));
121 for (i
= 0; i
< histcount
; i
++) {
123 printf("%7lld %7lld %7lld %7lld %6.2f\n", hist
[i
].low
,
124 hist
[i
].high
, hist
[i
].count
, hist
[i
].blocks
,
125 hist
[i
].blocks
* 100.0 / totblocks
);
137 for (i
= 0; i
< agcount
; i
++)
138 if (aglist
[i
] == agno
)
143 #define NR_EXTENTS 128
149 struct fsmap_head
*fsmap
;
150 struct fsmap
*extent
;
153 struct xfs_fd
*xfd
= &file
->xfd
;
156 unsigned long long freeblks
= 0;
157 unsigned long long freeexts
= 0;
161 fsmap
= malloc(fsmap_sizeof(NR_EXTENTS
));
163 fprintf(stderr
, _("%s: fsmap malloc failed.\n"), progname
);
168 memset(fsmap
, 0, sizeof(*fsmap
));
169 fsmap
->fmh_count
= NR_EXTENTS
;
171 h
= fsmap
->fmh_keys
+ 1;
172 if (agno
!= NULLAGNUMBER
) {
173 l
->fmr_physical
= cvt_agbno_to_b(xfd
, agno
, 0);
174 h
->fmr_physical
= cvt_agbno_to_b(xfd
, agno
+ 1, 0);
175 l
->fmr_device
= h
->fmr_device
= file
->fs_path
.fs_datadev
;
178 h
->fmr_physical
= ULLONG_MAX
;
179 l
->fmr_device
= h
->fmr_device
= file
->fs_path
.fs_rtdev
;
181 h
->fmr_owner
= ULLONG_MAX
;
182 h
->fmr_flags
= UINT_MAX
;
183 h
->fmr_offset
= ULLONG_MAX
;
186 ret
= ioctl(file
->xfd
.fd
, FS_IOC_GETFSMAP
, fsmap
);
188 fprintf(stderr
, _("%s: FS_IOC_GETFSMAP [\"%s\"]: %s\n"),
189 progname
, file
->name
, strerror(errno
));
195 /* No more extents to map, exit */
196 if (!fsmap
->fmh_entries
)
199 for (i
= 0, extent
= fsmap
->fmh_recs
;
200 i
< fsmap
->fmh_entries
;
202 if (!(extent
->fmr_flags
& FMR_OF_SPECIAL_OWNER
) ||
203 extent
->fmr_owner
!= XFS_FMR_OWN_FREE
)
205 agbno
= cvt_b_to_agbno(xfd
, extent
->fmr_physical
);
206 aglen
= cvt_b_to_off_fsbt(xfd
, extent
->fmr_length
);
210 addtohist(agno
, agbno
, aglen
);
213 p
= &fsmap
->fmh_recs
[fsmap
->fmh_entries
- 1];
214 if (p
->fmr_flags
& FMR_OF_LAST
)
216 fsmap_advance(fsmap
);
220 if (agno
== NULLAGNUMBER
)
221 printf(_(" rtdev %10llu %10llu\n"), freeexts
,
224 printf(_("%10u %10llu %10llu\n"), agno
, freeexts
,
236 aglist
= realloc(aglist
, (agcount
+ 1) * sizeof(*aglist
));
239 printf(_("Unrecognized AG number: %s\n"), a
);
251 struct xfs_fsop_geom
*fsgeom
= &file
->xfd
.fsgeom
;
254 int speced
= 0; /* only one of -b -e -h or -m */
256 agcount
= dumpflag
= equalsize
= multsize
= optind
= gflag
= 0;
257 histcount
= seen1
= summaryflag
= 0;
258 totblocks
= totexts
= 0;
263 while ((c
= getopt(argc
, argv
, "a:bde:gh:m:rs")) != EOF
) {
280 equalsize
= cvt_s64(optarg
, 0);
282 return command_usage(&freesp_cmd
);
290 if (speced
&& !histcount
)
292 /* addhistent increments histcount */
293 x
= cvt_s64(optarg
, 0);
295 return command_usage(&freesp_cmd
);
302 multsize
= cvt_s64(optarg
, 0);
304 return command_usage(&freesp_cmd
);
315 return command_usage(&freesp_cmd
);
322 histinit(fsgeom
->agblocks
);
325 return command_usage(&freesp_cmd
);
329 * Report on freespace usage in xfs filesystem.
336 struct xfs_fsop_geom
*fsgeom
= &file
->xfd
.fsgeom
;
339 if (!init(argc
, argv
))
342 printf(_(" AG extents blocks\n"));
344 scan_ag(NULLAGNUMBER
);
345 for (agno
= 0; !rtflag
&& agno
< fsgeom
->agcount
; agno
++) {
349 if (histcount
&& !gflag
)
352 printf(_("total free extents %lld\n"), totexts
);
353 printf(_("total free blocks %lld\n"), totblocks
);
354 printf(_("average free extent size %g\n"),
355 (double)totblocks
/ (double)totexts
);
369 "Examine filesystem free space\n"
371 " -a agno -- Scan only the given AG agno.\n"
372 " -b -- binary histogram bin size\n"
373 " -d -- debug output\n"
374 " -e bsize -- Use fixed histogram bin size of bsize\n"
375 " -g -- Print only a per-AG summary.\n"
376 " -h hbsz -- Use custom histogram bin size of h1.\n"
377 " Multiple specifications are allowed.\n"
378 " -m bmult -- Use histogram bin size multiplier of bmult.\n"
379 " -r -- Display realtime device free space information.\n"
380 " -s -- Emit freespace summary information.\n"
382 "Only one of -b, -e, -h, or -m may be specified.\n"
390 freesp_cmd
.name
= "freesp";
391 freesp_cmd
.altname
= "fsp";
392 freesp_cmd
.cfunc
= freesp_f
;
393 freesp_cmd
.argmin
= 0;
394 freesp_cmd
.argmax
= -1;
395 freesp_cmd
.args
= "[-dgrs] [-a agno]... [ -b | -e bsize | -h h1... | -m bmult ]";
396 freesp_cmd
.flags
= CMD_FLAG_ONESHOT
;
397 freesp_cmd
.oneline
= _("Examine filesystem free space");
398 freesp_cmd
.help
= freesp_help
;
400 add_command(&freesp_cmd
);