]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
spaceman: add FITRIM support
authorDave Chinner <dchinner@redhat.com>
Tue, 10 Feb 2015 22:10:21 +0000 (09:10 +1100)
committerDave Chinner <david@fromorbit.com>
Tue, 10 Feb 2015 22:10:21 +0000 (09:10 +1100)
Add support for discarding free space extents via the FITRIM
command. Make it easy to discard a single range, an entire AG or all
the freespace in the filesystem.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
spaceman/Makefile
spaceman/init.c
spaceman/space.h
spaceman/trim.c [new file with mode: 0644]

index ff8d23ef2fae26878243aa12a44c20a2627b5dde..9fb914233fc744ef7a0376200b295553866af04a 100644 (file)
@@ -8,7 +8,7 @@ include $(TOPDIR)/include/builddefs
 LTCOMMAND = xfs_spaceman
 HFILES = init.h space.h
 CFILES = init.c \
-       file.c
+       file.c trim.c
 
 LLDLIBS = $(LIBXCMD)
 LTDEPENDENCIES = $(LIBXCMD)
index 98c79e5485829a62a69fe47151c3da314f252f4f..314b5aac80f505ca3f7d3e9bd53b1aa2f9e3c771 100644 (file)
@@ -40,6 +40,7 @@ init_commands(void)
        file_init();
        help_init();
        quit_init();
+       trim_init();
 }
 
 static int
index 6e1bc5205e42a1d8473affb6601da926e300e52f..7b4f03455bbae2899e0fb3f5ad4f7134ca635b5e 100644 (file)
@@ -34,3 +34,4 @@ extern int    addfile(char *, int , xfs_fsop_geom_t *, int);
 extern void    file_init(void);
 extern void    help_init(void);
 extern void    quit_init(void);
+extern void    trim_init(void);
diff --git a/spaceman/trim.c b/spaceman/trim.c
new file mode 100644 (file)
index 0000000..11385ff
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2012 Red Hat, Inc.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write the Free Software Foundation,
+ * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <xfs/xfs.h>
+#include <xfs/xfs_types.h>
+#include <xfs/command.h>
+#include <linux/fs.h>
+#include "init.h"
+#include "space.h"
+#include "input.h"
+
+#ifndef FITRIM
+#define FITRIM          _IOWR('X', 121, struct fstrim_range)    /* Trim */
+
+struct fstrim_range {
+       __u64 start;
+       __u64 len;
+       __u64 minlen;
+};
+#endif
+
+static cmdinfo_t trim_cmd;
+
+/*
+ * Report on trimace usage in xfs filesystem.
+ */
+static int
+trim_f(
+       int             argc,
+       char            **argv)
+{
+       struct fstrim_range trim = {0};
+       xfs_agnumber_t  agno = 0;
+       off64_t         offset = 0;
+       ssize_t         length = 0;
+       ssize_t         minlen = 0;
+       int             aflag = 0;
+       int             fflag = 0;
+       int             ret;
+       int             c;
+
+       while ((c = getopt(argc, argv, "a:fm:")) != EOF) {
+               switch (c) {
+               case 'a':
+                       if (fflag)
+                               return command_usage(&trim_cmd);
+                       aflag = 1;
+                       agno = atoi(optarg);
+                       break;
+               case 'f':
+                       if (aflag)
+                               return command_usage(&trim_cmd);
+                       fflag = 1;
+                       break;
+               case 'm':
+                       minlen = cvtnum(file->geom.blocksize,
+                                       file->geom.sectsize, argv[optind]);
+                       break;
+               default:
+                       return command_usage(&trim_cmd);
+               }
+       }
+
+       if (optind != argc - 2 && !(aflag || fflag))
+               return command_usage(&trim_cmd);
+       if (optind != argc) {
+               offset = cvtnum(file->geom.blocksize, file->geom.sectsize,
+                               argv[optind]);
+               length = cvtnum(file->geom.blocksize, file->geom.sectsize,
+                               argv[optind + 1]);
+       } else if (agno) {
+               offset = agno * file->geom.agblocks * file->geom.blocksize;
+               length = file->geom.agblocks * file->geom.blocksize;
+       } else {
+               offset = 0;
+               length = file->geom.datablocks * file->geom.blocksize;
+       }
+
+       trim.start = offset;
+       trim.len = length;
+       trim.minlen = minlen;
+
+       ret = ioctl(file->fd, FITRIM, (unsigned long)&trim);
+       if (ret < 0) {
+               fprintf(stderr, "%s: ioctl(FITRIM) [\"%s\"]: "
+                       "%s\n", progname, file->name, strerror(errno));
+               exitcode = 1;
+               return 0;
+       }
+       return 0;
+}
+
+static void
+trim_help(void)
+{
+       printf(_(
+"\n"
+"Discard filesystem free space\n"
+"\n"
+"Options: [-m minlen] [-f]|[-a agno]|[offset length]\n"
+"\n"
+" -m minlen -- skip freespace extents smaller than minlen\n"
+" -f -- trim all the freespace in the entire filesystem\n"
+" -a agno -- trim all the freespace in the given AG agno\n"
+" offset length -- trim the freespace in the range {offset, length}\n"
+"\n"));
+
+}
+
+void
+trim_init(void)
+{
+       trim_cmd.name = "trim";
+       trim_cmd.altname = "tr";
+       trim_cmd.cfunc = trim_f;
+       trim_cmd.argmin = 1;
+       trim_cmd.argmax = 4;
+       trim_cmd.args = "[-m minlen] [-f]|[-a agno]|[offset length]\n";
+       trim_cmd.flags = CMD_FLAG_GLOBAL;
+       trim_cmd.oneline = _("Discard filesystem free space");
+       trim_cmd.help = trim_help;
+
+       add_command(&trim_cmd);
+}
+