]>
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>
17 typedef struct histent
26 static xfs_agnumber_t
*aglist
;
27 static histent_t
*hist
;
29 static long long equalsize
;
30 static long long multsize
;
33 static int summaryflag
;
36 static long long totblocks
;
37 static long long totexts
;
39 static cmdinfo_t freesp_cmd
;
45 if (histcount
== INT_MAX
) {
46 printf(_("Too many histogram buckets.\n"));
49 hist
= realloc(hist
, (histcount
+ 1) * sizeof(*hist
));
52 hist
[histcount
].low
= h
;
53 hist
[histcount
].count
= hist
[histcount
].blocks
= 0;
68 printf("%8d %8d %8"PRId64
"\n", agno
, agbno
, len
);
71 for (i
= 0; i
< histcount
; i
++) {
72 if (hist
[i
].high
>= len
) {
74 hist
[i
].blocks
+= len
;
85 return ((histent_t
*)a
)->low
- ((histent_t
*)b
)->low
;
95 for (i
= 1; i
< maxlen
; i
+= equalsize
)
97 } else if (multsize
) {
98 for (i
= 1; i
< maxlen
; i
*= multsize
)
103 qsort(hist
, histcount
, sizeof(*hist
), hcmp
);
105 for (i
= 0; i
< histcount
; i
++) {
106 if (i
< histcount
- 1)
107 hist
[i
].high
= hist
[i
+ 1].low
- 1;
109 hist
[i
].high
= maxlen
;
118 printf("%7s %7s %7s %7s %6s\n",
119 _("from"), _("to"), _("extents"), _("blocks"), _("pct"));
120 for (i
= 0; i
< histcount
; i
++) {
122 printf("%7lld %7lld %7lld %7lld %6.2f\n", hist
[i
].low
,
123 hist
[i
].high
, hist
[i
].count
, hist
[i
].blocks
,
124 hist
[i
].blocks
* 100.0 / totblocks
);
136 for (i
= 0; i
< agcount
; i
++)
137 if (aglist
[i
] == agno
)
142 #define NR_EXTENTS 128
148 struct fsmap_head
*fsmap
;
149 struct fsmap
*extent
;
152 off64_t blocksize
= file
->geom
.blocksize
;
156 unsigned long long freeblks
= 0;
157 unsigned long long freeexts
= 0;
161 bperag
= (off64_t
)file
->geom
.agblocks
* blocksize
;
163 fsmap
= malloc(fsmap_sizeof(NR_EXTENTS
));
165 fprintf(stderr
, _("%s: fsmap malloc failed.\n"), progname
);
170 memset(fsmap
, 0, sizeof(*fsmap
));
171 fsmap
->fmh_count
= NR_EXTENTS
;
173 h
= fsmap
->fmh_keys
+ 1;
174 if (agno
!= NULLAGNUMBER
) {
175 l
->fmr_physical
= agno
* bperag
;
176 h
->fmr_physical
= ((agno
+ 1) * bperag
) - 1;
177 l
->fmr_device
= h
->fmr_device
= file
->fs_path
.fs_datadev
;
180 h
->fmr_physical
= ULLONG_MAX
;
181 l
->fmr_device
= h
->fmr_device
= file
->fs_path
.fs_rtdev
;
183 h
->fmr_owner
= ULLONG_MAX
;
184 h
->fmr_flags
= UINT_MAX
;
185 h
->fmr_offset
= ULLONG_MAX
;
188 ret
= ioctl(file
->fd
, FS_IOC_GETFSMAP
, fsmap
);
190 fprintf(stderr
, _("%s: FS_IOC_GETFSMAP [\"%s\"]: %s\n"),
191 progname
, file
->name
, strerror(errno
));
197 /* No more extents to map, exit */
198 if (!fsmap
->fmh_entries
)
201 for (i
= 0, extent
= fsmap
->fmh_recs
;
202 i
< fsmap
->fmh_entries
;
204 if (!(extent
->fmr_flags
& FMR_OF_SPECIAL_OWNER
) ||
205 extent
->fmr_owner
!= XFS_FMR_OWN_FREE
)
207 agbno
= (extent
->fmr_physical
- (bperag
* agno
)) /
209 aglen
= extent
->fmr_length
/ blocksize
;
213 addtohist(agno
, agbno
, aglen
);
216 p
= &fsmap
->fmh_recs
[fsmap
->fmh_entries
- 1];
217 if (p
->fmr_flags
& FMR_OF_LAST
)
219 fsmap_advance(fsmap
);
223 if (agno
== NULLAGNUMBER
)
224 printf(_(" rtdev %10llu %10llu\n"), freeexts
,
227 printf(_("%10u %10llu %10llu\n"), agno
, freeexts
,
239 aglist
= realloc(aglist
, (agcount
+ 1) * sizeof(*aglist
));
242 printf(_("Unrecognized AG number: %s\n"), a
);
256 int speced
= 0; /* only one of -b -e -h or -m */
258 agcount
= dumpflag
= equalsize
= multsize
= optind
= gflag
= 0;
259 histcount
= seen1
= summaryflag
= 0;
260 totblocks
= totexts
= 0;
265 while ((c
= getopt(argc
, argv
, "a:bde:gh:m:rs")) != EOF
) {
282 equalsize
= cvt_s64(optarg
, 0);
284 return command_usage(&freesp_cmd
);
292 if (speced
&& !histcount
)
294 /* addhistent increments histcount */
295 x
= cvt_s64(optarg
, 0);
297 return command_usage(&freesp_cmd
);
304 multsize
= cvt_s64(optarg
, 0);
306 return command_usage(&freesp_cmd
);
317 return command_usage(&freesp_cmd
);
324 histinit(file
->geom
.agblocks
);
327 return command_usage(&freesp_cmd
);
331 * Report on freespace usage in xfs filesystem.
340 if (!init(argc
, argv
))
343 printf(_(" AG extents blocks\n"));
345 scan_ag(NULLAGNUMBER
);
346 for (agno
= 0; !rtflag
&& agno
< file
->geom
.agcount
; agno
++) {
350 if (histcount
&& !gflag
)
353 printf(_("total free extents %lld\n"), totexts
);
354 printf(_("total free blocks %lld\n"), totblocks
);
355 printf(_("average free extent size %g\n"),
356 (double)totblocks
/ (double)totexts
);
370 "Examine filesystem free space\n"
372 " -a agno -- Scan only the given AG agno.\n"
373 " -b -- binary histogram bin size\n"
374 " -d -- debug output\n"
375 " -e bsize -- Use fixed histogram bin size of bsize\n"
376 " -g -- Print only a per-AG summary.\n"
377 " -h hbsz -- Use custom histogram bin size of h1.\n"
378 " Multiple specifications are allowed.\n"
379 " -m bmult -- Use histogram bin size multiplier of bmult.\n"
380 " -r -- Display realtime device free space information.\n"
381 " -s -- Emit freespace summary information.\n"
383 "Only one of -b, -e, -h, or -m may be specified.\n"
391 freesp_cmd
.name
= "freesp";
392 freesp_cmd
.altname
= "fsp";
393 freesp_cmd
.cfunc
= freesp_f
;
394 freesp_cmd
.argmin
= 0;
395 freesp_cmd
.argmax
= -1;
396 freesp_cmd
.args
= "[-dgrs] [-a agno]... [ -b | -e bsize | -h h1... | -m bmult ]";
397 freesp_cmd
.flags
= CMD_FLAG_ONESHOT
;
398 freesp_cmd
.oneline
= _("Examine filesystem free space");
399 freesp_cmd
.help
= freesp_help
;
401 add_command(&freesp_cmd
);