Start 1.33.0 development cycle
[oweals/busybox.git] / util-linux / fstrim.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * fstrim.c - discard the part (or whole) of mounted filesystem.
4  *
5  * 03 March 2012 - Malek Degachi <malek-degachi@laposte.net>
6  * Adapted for busybox from util-linux-2.12a.
7  *
8  * Licensed under GPLv2 or later, see file LICENSE in this source tree.
9  */
10 //config:config FSTRIM
11 //config:       bool "fstrim (4.4 kb)"
12 //config:       default y
13 //config:       select PLATFORM_LINUX
14 //config:       help
15 //config:       Discard unused blocks on a mounted filesystem.
16
17 //applet:IF_FSTRIM(APPLET_NOEXEC(fstrim, fstrim, BB_DIR_SBIN, BB_SUID_DROP, fstrim))
18
19 //kbuild:lib-$(CONFIG_FSTRIM) += fstrim.o
20
21 //usage:#define fstrim_trivial_usage
22 //usage:       "[OPTIONS] MOUNTPOINT"
23 //usage:#define fstrim_full_usage "\n\n"
24 //usage:        IF_LONG_OPTS(
25 //usage:       "        -o,--offset OFFSET      Offset in bytes to discard from"
26 //usage:     "\n        -l,--length LEN         Bytes to discard"
27 //usage:     "\n        -m,--minimum MIN        Minimum extent length"
28 //usage:     "\n        -v,--verbose            Print number of discarded bytes"
29 //usage:        )
30 //usage:        IF_NOT_LONG_OPTS(
31 //usage:       "        -o OFFSET       Offset in bytes to discard from"
32 //usage:     "\n        -l LEN          Bytes to discard"
33 //usage:     "\n        -m MIN          Minimum extent length"
34 //usage:     "\n        -v              Print number of discarded bytes"
35 //usage:        )
36
37 #include "libbb.h"
38 #include <linux/fs.h>
39
40 #ifndef FITRIM
41 struct fstrim_range {
42         uint64_t start;
43         uint64_t len;
44         uint64_t minlen;
45 };
46 #define FITRIM          _IOWR('X', 121, struct fstrim_range)
47 #endif
48
49 int fstrim_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
50 int fstrim_main(int argc UNUSED_PARAM, char **argv)
51 {
52         struct fstrim_range range;
53         char *arg_o, *arg_l, *arg_m, *mp;
54         unsigned opts;
55         int fd;
56
57         enum {
58                 OPT_o = (1 << 0),
59                 OPT_l = (1 << 1),
60                 OPT_m = (1 << 2),
61                 OPT_v = (1 << 3),
62         };
63
64 #if ENABLE_LONG_OPTS
65         static const char fstrim_longopts[] ALIGN1 =
66                 "offset\0"    Required_argument    "o"
67                 "length\0"    Required_argument    "l"
68                 "minimum\0"   Required_argument    "m"
69                 "verbose\0"   No_argument          "v"
70                 ;
71 #endif
72
73         opts = getopt32long(argv, "^"
74                         "o:l:m:v"
75                         "\0" "=1", fstrim_longopts,
76                         &arg_o, &arg_l, &arg_m
77         );
78
79         memset(&range, 0, sizeof(range));
80         range.len = ULLONG_MAX;
81
82         if (opts & OPT_o)
83                 range.start = xatoull_sfx(arg_o, kmg_i_suffixes);
84         if (opts & OPT_l)
85                 range.len = xatoull_sfx(arg_l, kmg_i_suffixes);
86         if (opts & OPT_m)
87                 range.minlen = xatoull_sfx(arg_m, kmg_i_suffixes);
88
89         mp = argv[optind];
90 //Wwhy bother checking that it's a blockdev?
91 //      if (find_block_device(mp)) {
92                 fd = xopen_nonblocking(mp);
93
94                 /* On ENOTTY error, util-linux 2.31 says:
95                  * "fstrim: FILE: the discard operation is not supported"
96                  */
97                 xioctl(fd, FITRIM, &range);
98
99                 if (ENABLE_FEATURE_CLEAN_UP)
100                         close(fd);
101
102                 if (opts & OPT_v)
103                         printf("%s: %llu bytes trimmed\n", mp, (unsigned long long)range.len);
104                 return EXIT_SUCCESS;
105 //      }
106         return EXIT_FAILURE;
107 }