]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - spaceman/freesp.c
2 * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
3 * Copyright (c) 2012 Red Hat, Inc.
4 * Copyright (c) 2017 Oracle.
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it would be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 #include <linux/fiemap.h>
29 typedef struct histent
38 static xfs_agnumber_t
*aglist
;
39 static histent_t
*hist
;
41 static long long equalsize
;
42 static long long multsize
;
45 static int summaryflag
;
48 static long long totblocks
;
49 static long long totexts
;
51 static cmdinfo_t freesp_cmd
;
57 if (histcount
== INT_MAX
) {
58 printf(_("Too many histogram buckets.\n"));
61 hist
= realloc(hist
, (histcount
+ 1) * sizeof(*hist
));
64 hist
[histcount
].low
= h
;
65 hist
[histcount
].count
= hist
[histcount
].blocks
= 0;
80 printf("%8d %8d %8"PRId64
"\n", agno
, agbno
, len
);
83 for (i
= 0; i
< histcount
; i
++) {
84 if (hist
[i
].high
>= len
) {
86 hist
[i
].blocks
+= len
;
97 return ((histent_t
*)a
)->low
- ((histent_t
*)b
)->low
;
107 for (i
= 1; i
< maxlen
; i
+= equalsize
)
109 } else if (multsize
) {
110 for (i
= 1; i
< maxlen
; i
*= multsize
)
115 qsort(hist
, histcount
, sizeof(*hist
), hcmp
);
117 for (i
= 0; i
< histcount
; i
++) {
118 if (i
< histcount
- 1)
119 hist
[i
].high
= hist
[i
+ 1].low
- 1;
121 hist
[i
].high
= maxlen
;
130 printf("%7s %7s %7s %7s %6s\n",
131 _("from"), _("to"), _("extents"), _("blocks"), _("pct"));
132 for (i
= 0; i
< histcount
; i
++) {
134 printf("%7lld %7lld %7lld %7lld %6.2f\n", hist
[i
].low
,
135 hist
[i
].high
, hist
[i
].count
, hist
[i
].blocks
,
136 hist
[i
].blocks
* 100.0 / totblocks
);
148 for (i
= 0; i
< agcount
; i
++)
149 if (aglist
[i
] == agno
)
154 #define NR_EXTENTS 128
160 struct fsmap_head
*fsmap
;
161 struct fsmap
*extent
;
164 off64_t blocksize
= file
->geom
.blocksize
;
168 unsigned long long freeblks
= 0;
169 unsigned long long freeexts
= 0;
173 bperag
= (off64_t
)file
->geom
.agblocks
* blocksize
;
175 fsmap
= malloc(fsmap_sizeof(NR_EXTENTS
));
177 fprintf(stderr
, _("%s: fsmap malloc failed.\n"), progname
);
182 memset(fsmap
, 0, sizeof(*fsmap
));
183 fsmap
->fmh_count
= NR_EXTENTS
;
185 h
= fsmap
->fmh_keys
+ 1;
186 if (agno
!= NULLAGNUMBER
) {
187 l
->fmr_physical
= agno
* bperag
;
188 h
->fmr_physical
= ((agno
+ 1) * bperag
) - 1;
189 l
->fmr_device
= h
->fmr_device
= file
->fs_path
.fs_datadev
;
192 h
->fmr_physical
= ULLONG_MAX
;
193 l
->fmr_device
= h
->fmr_device
= file
->fs_path
.fs_rtdev
;
195 h
->fmr_owner
= ULLONG_MAX
;
196 h
->fmr_flags
= UINT_MAX
;
197 h
->fmr_offset
= ULLONG_MAX
;
200 ret
= ioctl(file
->fd
, FS_IOC_GETFSMAP
, fsmap
);
202 fprintf(stderr
, _("%s: FS_IOC_GETFSMAP [\"%s\"]: %s\n"),
203 progname
, file
->name
, strerror(errno
));
209 /* No more extents to map, exit */
210 if (!fsmap
->fmh_entries
)
213 for (i
= 0, extent
= fsmap
->fmh_recs
;
214 i
< fsmap
->fmh_entries
;
216 if (!(extent
->fmr_flags
& FMR_OF_SPECIAL_OWNER
) ||
217 extent
->fmr_owner
!= XFS_FMR_OWN_FREE
)
219 agbno
= (extent
->fmr_physical
- (bperag
* agno
)) /
221 aglen
= extent
->fmr_length
/ blocksize
;
225 addtohist(agno
, agbno
, aglen
);
228 p
= &fsmap
->fmh_recs
[fsmap
->fmh_entries
- 1];
229 if (p
->fmr_flags
& FMR_OF_LAST
)
231 fsmap_advance(fsmap
);
235 if (agno
== NULLAGNUMBER
)
236 printf(_(" rtdev %10llu %10llu\n"), freeexts
,
239 printf(_("%10u %10llu %10llu\n"), agno
, freeexts
,
251 aglist
= realloc(aglist
, (agcount
+ 1) * sizeof(*aglist
));
254 printf(_("Unrecognized AG number: %s\n"), a
);
268 int speced
= 0; /* only one of -b -e -h or -m */
270 agcount
= dumpflag
= equalsize
= multsize
= optind
= gflag
= 0;
271 histcount
= seen1
= summaryflag
= 0;
272 totblocks
= totexts
= 0;
277 while ((c
= getopt(argc
, argv
, "a:bde:gh:m:rs")) != EOF
) {
294 equalsize
= cvt_s64(optarg
, 0);
296 return command_usage(&freesp_cmd
);
304 if (speced
&& !histcount
)
306 /* addhistent increments histcount */
307 x
= cvt_s64(optarg
, 0);
309 return command_usage(&freesp_cmd
);
316 multsize
= cvt_s64(optarg
, 0);
318 return command_usage(&freesp_cmd
);
329 return command_usage(&freesp_cmd
);
336 histinit(file
->geom
.agblocks
);
339 return command_usage(&freesp_cmd
);
343 * Report on freespace usage in xfs filesystem.
352 if (!init(argc
, argv
))
355 printf(_(" AG extents blocks\n"));
357 scan_ag(NULLAGNUMBER
);
358 for (agno
= 0; !rtflag
&& agno
< file
->geom
.agcount
; agno
++) {
362 if (histcount
&& !gflag
)
365 printf(_("total free extents %lld\n"), totexts
);
366 printf(_("total free blocks %lld\n"), totblocks
);
367 printf(_("average free extent size %g\n"),
368 (double)totblocks
/ (double)totexts
);
382 "Examine filesystem free space\n"
384 " -a agno -- Scan only the given AG agno.\n"
385 " -b -- binary histogram bin size\n"
386 " -d -- debug output\n"
387 " -e bsize -- Use fixed histogram bin size of bsize\n"
388 " -g -- Print only a per-AG summary.\n"
389 " -h hbsz -- Use custom histogram bin size of h1.\n"
390 " Multiple specifications are allowed.\n"
391 " -m bmult -- Use histogram bin size multiplier of bmult.\n"
392 " -r -- Display realtime device free space information.\n"
393 " -s -- Emit freespace summary information.\n"
395 "Only one of -b, -e, -h, or -m may be specified.\n"
403 freesp_cmd
.name
= "freesp";
404 freesp_cmd
.altname
= "fsp";
405 freesp_cmd
.cfunc
= freesp_f
;
406 freesp_cmd
.argmin
= 0;
407 freesp_cmd
.argmax
= -1;
408 freesp_cmd
.args
= "[-dgrs] [-a agno]... [ -b | -e bsize | -h h1... | -m bmult ]";
409 freesp_cmd
.flags
= CMD_FLAG_ONESHOT
;
410 freesp_cmd
.oneline
= _("Examine filesystem free space");
411 freesp_cmd
.help
= freesp_help
;
413 add_command(&freesp_cmd
);