[PATCH] Add fstrim support to restore NAND/eMMC write performance.

eugenesan at gmail.com eugenesan at gmail.com
Fri Feb 22 12:43:36 UTC 2013


From: Malek Degachi <malek-degachi at laposte.net>

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

Signed-off-by: Eugene San (eugenesan) <eugenesan at gmail.com>
---
 include/applets.src.h |   1 +
 util-linux/Config.src |   7 ++++
 util-linux/Kbuild.src |   1 +
 util-linux/fstrim.c   | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 123 insertions(+)
 create mode 100644 util-linux/fstrim.c

diff --git a/include/applets.src.h b/include/applets.src.h
index 29ab167..c9244fb 100644
--- a/include/applets.src.h
+++ b/include/applets.src.h
@@ -161,6 +161,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))
diff --git a/util-linux/Config.src b/util-linux/Config.src
index 6c1b928..a82817c 100644
--- a/util-linux/Config.src
+++ b/util-linux/Config.src
@@ -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
diff --git a/util-linux/Kbuild.src b/util-linux/Kbuild.src
index 468fc6b..429cf11 100644
--- a/util-linux/Kbuild.src
+++ b/util-linux/Kbuild.src
@@ -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
index 0000000..915de06
--- /dev/null
+++ b/util-linux/fstrim.c
@@ -0,0 +1,114 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * fstrim.c - discard the part (or whole) of mounted filesystem.
+ *
+ * 03 March 2012 - Malek Degachi <malek-degachi at 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";
+	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);
+		close(fd);
+
+		if (opts & OPT_v)
+			printf("%s: %llu bytes was trimmed\n", argv[optind], range.len);
+	}
+
+	return EXIT_SUCCESS;
+}
-- 
1.8.1.1



More information about the busybox mailing list