]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - spaceman/trim.c
xfs: don't assert when on-disk btree pointers are garbage
[thirdparty/xfsprogs-dev.git] / spaceman / trim.c
CommitLineData
c6e8a429
DC
1/*
2 * Copyright (c) 2012 Red Hat, Inc.
3 * All Rights Reserved.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19#include "libxfs.h"
c6e8a429
DC
20#include "command.h"
21#include "init.h"
cccf6abc 22#include "path.h"
c6e8a429
DC
23#include "space.h"
24#include "input.h"
25
26static cmdinfo_t trim_cmd;
27
28/*
29 * Trim unused space in xfs filesystem.
30 */
31static int
32trim_f(
33 int argc,
34 char **argv)
35{
36 struct fstrim_range trim = {0};
37 xfs_agnumber_t agno = 0;
38 off64_t offset = 0;
39 ssize_t length = 0;
40 ssize_t minlen = 0;
41 int aflag = 0;
42 int fflag = 0;
43 int ret;
44 int c;
45
46 while ((c = getopt(argc, argv, "a:fm:")) != EOF) {
47 switch (c) {
48 case 'a':
49 aflag = 1;
50 agno = cvt_u32(optarg, 10);
51 if (errno) {
52 printf(_("bad agno value %s\n"), optarg);
53 return command_usage(&trim_cmd);
54 }
55 break;
56 case 'f':
57 fflag = 1;
58 break;
59 case 'm':
60 minlen = cvtnum(file->geom.blocksize,
61 file->geom.sectsize, optarg);
62 break;
63 default:
64 return command_usage(&trim_cmd);
65 }
66 }
67
68 if (aflag && fflag)
69 return command_usage(&trim_cmd);
70
71 if (optind != argc - 2 && !(aflag || fflag))
72 return command_usage(&trim_cmd);
73 if (optind != argc) {
74 offset = cvtnum(file->geom.blocksize, file->geom.sectsize,
75 argv[optind]);
76 length = cvtnum(file->geom.blocksize, file->geom.sectsize,
77 argv[optind + 1]);
78 } else if (agno) {
eb125dcb 79 offset = (off64_t)agno * file->geom.agblocks * file->geom.blocksize;
c6e8a429
DC
80 length = file->geom.agblocks * file->geom.blocksize;
81 } else {
82 offset = 0;
83 length = file->geom.datablocks * file->geom.blocksize;
84 }
85
86 trim.start = offset;
87 trim.len = length;
88 trim.minlen = minlen;
89
90 ret = ioctl(file->fd, FITRIM, (unsigned long)&trim);
91 if (ret < 0) {
92 fprintf(stderr, "%s: ioctl(FITRIM) [\"%s\"]: %s\n",
93 progname, file->name, strerror(errno));
94 exitcode = 1;
95 }
96 return 0;
97}
98
99static void
100trim_help(void)
101{
102 printf(_(
103"\n"
104"Discard filesystem free space\n"
105"\n"
106" -a agno -- trim all the freespace in the given AG agno\n"
107" -f -- trim all the freespace in the entire filesystem\n"
108" offset length -- trim the freespace in the range {offset, length}\n"
109" -m minlen -- skip freespace extents smaller than minlen\n"
110"\n"
111"One of -a, -f, or the offset/length pair are required.\n"
112"\n"));
113
114}
115
116void
117trim_init(void)
118{
119 trim_cmd.name = "trim";
120 trim_cmd.altname = "tr";
121 trim_cmd.cfunc = trim_f;
122 trim_cmd.argmin = 1;
123 trim_cmd.argmax = 4;
124 trim_cmd.args = "[-m minlen] ( -a agno | -f | offset length )";
125 trim_cmd.flags = CMD_FLAG_ONESHOT;
126 trim_cmd.oneline = _("Discard filesystem free space");
127 trim_cmd.help = trim_help;
128
129 add_command(&trim_cmd);
130}
131