fstrim: New applet
authorMalek Degachi <malek-degachi@laposte.net>
Sat, 9 Nov 2013 20:27:27 +0000 (21:27 +0100)
committerBernhard Reutner-Fischer <rep.dot.nop@gmail.com>
Sat, 9 Nov 2013 21:14:33 +0000 (22:14 +0100)
fstrim applet is a port from util-linux.

"Trimming" your NAND/eMMC storage will restore the write performance
back to normal after having slow down issues on sequential write and
random write due to usage over time.

Good reading on subject:
http://forum.xda-developers.com/showthread.php?t=1971852

(with long options and CLEAN_UP turned on)
function                                             old     new   delta
.rodata                                           148494  148791    +297
fstrim_main                                            -     283    +283
fstrim_sfx                                             -     128    +128
packed_usage                                       28826   28903     +77
applet_main                                         2760    2768      +8
applet_names                                        2343    2350      +7
applet_nameofs                                       690     692      +2
------------------------------------------------------------------------------
(add/remove: 3/0 grow/shrink: 5/0 up/down: 802/0)             Total: 802 bytes

Signed-off-by: Malek Degachi <malek-degachi@laposte.net>
Cc: Eugene San (eugenesan) <eugenesan@gmail.com>
Signed-off-by: Bernhard Reutner-Fischer <rep.dot.nop@gmail.com>
include/applets.src.h
util-linux/Config.src
util-linux/Kbuild.src
util-linux/fstrim.c [new file with mode: 0644]

index 3a47e15b99166c1c008c9c1ce0f3ad100233729a..5268200f5a6cb1f3d26d47dbf314dabaf77182d5 100644 (file)
@@ -167,6 +167,7 @@ IF_FSCK(APPLET(fsck, BB_DIR_SBIN, BB_SUID_DROP))
 //IF_E2FSCK(APPLET_ODDNAME(fsck.ext2, e2fsck, BB_DIR_SBIN, BB_SUID_DROP, fsck_ext2))
 //IF_E2FSCK(APPLET_ODDNAME(fsck.ext3, e2fsck, BB_DIR_SBIN, BB_SUID_DROP, fsck_ext3))
 IF_FSCK_MINIX(APPLET_ODDNAME(fsck.minix, fsck_minix, BB_DIR_SBIN, BB_SUID_DROP, fsck_minix))
+IF_FSTRIM(APPLET(fstrim, BB_DIR_SBIN, BB_SUID_DROP))
 IF_FSYNC(APPLET_NOFORK(fsync, fsync, BB_DIR_BIN, BB_SUID_DROP, fsync))
 IF_FTPD(APPLET(ftpd, BB_DIR_USR_SBIN, BB_SUID_DROP))
 IF_FTPGET(APPLET_ODDNAME(ftpget, ftpgetput, BB_DIR_USR_BIN, BB_SUID_DROP, ftpget))
index 5a8b0063bb460463985db74b66560896191718d1..ef703972018af9cd9493440c2754a6ec2c2ebd47 100644 (file)
@@ -246,6 +246,13 @@ config FSCK_MINIX
          check for and attempt to repair any corruption that occurs to a minix
          filesystem.
 
+config FSTRIM
+       bool "fstrim"
+       default y
+       select PLATFORM_LINUX
+       help
+         Discard unused blocks on a mounted filesystem.
+
 config MKFS_EXT2
        bool "mkfs_ext2"
        default y
index 468fc6bc12f8a7339b9712d2f8b6a151d8dbe6e6..429cf1100946f1a978a7a46d7ba33a39005d120a 100644 (file)
@@ -18,6 +18,7 @@ lib-$(CONFIG_FINDFS)            += findfs.o
 lib-$(CONFIG_FLOCK)             += flock.o
 lib-$(CONFIG_FREERAMDISK)       += freeramdisk.o
 lib-$(CONFIG_FSCK_MINIX)        += fsck_minix.o
+lib-$(CONFIG_FSTRIM)            += fstrim.o
 lib-$(CONFIG_GETOPT)            += getopt.o
 lib-$(CONFIG_HEXDUMP)           += hexdump.o
 lib-$(CONFIG_HWCLOCK)           += hwclock.o
diff --git a/util-linux/fstrim.c b/util-linux/fstrim.c
new file mode 100644 (file)
index 0000000..2fa457b
--- /dev/null
@@ -0,0 +1,111 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * fstrim.c - discard the part (or whole) of mounted filesystem.
+ *
+ * 03 March 2012 - Malek Degachi <malek-degachi@laposte.net>
+ * Adapted for busybox from util-linux-2.12a.
+ *
+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
+ */
+
+//usage:#define fstrim_trivial_usage
+//usage:       "[Options] <mountpoint>"
+//usage:#define fstrim_full_usage "\n\n"
+//usage:       "Options:"
+//usage:       IF_LONG_OPTS(
+//usage:     "\n       -o,--offset=offset      offset in bytes to discard from"
+//usage:     "\n       -l,--length=length      length of bytes to discard from the offset"
+//usage:     "\n       -m,--minimum=minimum    minimum extent length to discard"
+//usage:     "\n       -v,--verbose            print number of discarded bytes"
+//usage:       )
+//usage:       IF_NOT_LONG_OPTS(
+//usage:     "\n       -o offset       offset in bytes to discard from"
+//usage:     "\n       -l length       length of bytes to discard from the offset"
+//usage:     "\n       -m minimum      minimum extent length to discard"
+//usage:     "\n       -v,             print number of discarded bytes"
+//usage:       )
+
+#include "libbb.h"
+#include <linux/fs.h>
+
+#ifndef FITRIM
+struct fstrim_range {
+       uint64_t start;
+       uint64_t len;
+       uint64_t minlen;
+};
+#define FITRIM         _IOWR('X', 121, struct fstrim_range)
+#endif
+
+static const struct suffix_mult fstrim_sfx[] = {
+       { "KiB", 1024 },
+       { "kiB", 1024 },
+       { "K", 1024 },
+       { "k", 1024 },
+       { "MiB", 1048576 },
+       { "miB", 1048576 },
+       { "M", 1048576 },
+       { "m", 1048576 },
+       { "GiB", 1073741824 },
+       { "giB", 1073741824 },
+       { "G", 1073741824 },
+       { "g", 1073741824 },
+       { "KB", 1000 },
+       { "MB", 1000000 },
+       { "GB", 1000000000 },
+       { "", 0 }
+};
+
+int fstrim_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int fstrim_main(int argc UNUSED_PARAM, char **argv)
+{
+       struct fstrim_range range;
+       char *arg_o;
+       char *arg_l;
+       char *arg_m;
+       unsigned opts;
+       int fd;
+
+       enum {
+               OPT_o = (1 << 0),
+               OPT_l = (1 << 1),
+               OPT_m = (1 << 2),
+               OPT_v = (1 << 3),
+       };
+
+#if ENABLE_LONG_OPTS
+       static const char getopt_longopts[] ALIGN1 =
+               "offset\0"    Required_argument    "o"
+               "length\0"    Required_argument    "l"
+               "minimum\0"   Required_argument    "m"
+               "verbose\0"   No_argument          "v"
+               ;
+       applet_long_options = getopt_longopts;
+#endif
+
+       opt_complementary = "=1"; /* exactly one non-option arg: the mountpoint */
+       opts = getopt32(argv, "o:l:m:v", &arg_o, &arg_l, &arg_m);
+
+       memset(&range, 0, sizeof(range));
+       range.len = ULLONG_MAX;
+
+       if (opts & OPT_o)
+               range.start = xatoull_sfx(arg_o, fstrim_sfx);
+       if (opts & OPT_l)
+               range.len = xatoull_sfx(arg_l, fstrim_sfx);
+       if (opts & OPT_m)
+               range.minlen = xatoull_sfx(arg_m, fstrim_sfx);
+
+       if (find_block_device(argv[optind])) {
+               fd = xopen_nonblocking(argv[optind]);
+               xioctl(fd, FITRIM, &range);
+               if (ENABLE_FEATURE_CLEAN_UP)
+                       close(fd);
+
+               if (opts & OPT_v)
+                       printf("%s: %llu bytes were trimmed\n", argv[optind], range.len);
+       }
+
+       return EXIT_SUCCESS;
+}
+