Add new defrag range ioctl that can also compress files on demand.
[btrfs-progs-unstable.git] / btrfs-defrag.c
blob9aab3ba482881b03e67ac09f06346a7f2767f29e
1 /*
2 * Copyright (C) 2010 Oracle. All rights reserved.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License v2 as published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public
14 * License along with this program; if not, write to the
15 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16 * Boston, MA 021110-1307, USA.
19 #ifndef __CHECKER__
20 #include <sys/ioctl.h>
21 #include <sys/mount.h>
22 #include "ioctl.h"
23 #endif
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <fcntl.h>
29 #include <ctype.h>
30 #include <unistd.h>
31 #include <dirent.h>
32 #include <libgen.h>
33 #include <getopt.h>
34 #include "kerncompat.h"
35 #include "ctree.h"
36 #include "transaction.h"
37 #include "utils.h"
38 #include "version.h"
40 static u64 parse_size(char *s)
42 int len = strlen(s);
43 char c;
44 u64 mult = 1;
46 if (!isdigit(s[len - 1])) {
47 c = tolower(s[len - 1]);
48 switch (c) {
49 case 'g':
50 mult *= 1024;
51 case 'm':
52 mult *= 1024;
53 case 'k':
54 mult *= 1024;
55 case 'b':
56 break;
57 default:
58 fprintf(stderr, "Unknown size descriptor %c\n", c);
59 exit(1);
61 s[len - 1] = '\0';
63 return atoll(s) * mult;
66 static void print_usage(void)
68 printf("usage: btrfs-defrag [-c] [-f] [-s start] [-l len] "
69 "[-t threshold] file ...\n");
70 exit(1);
73 int main(int ac, char **av)
75 int fd;
76 int compress = 0;
77 int flush = 0;
78 u64 start = 0;
79 u64 len = (u64)-1;
80 u32 thresh = 0;
81 int i;
82 int errors = 0;
83 int ret = 0;
84 int verbose = 0;
85 struct btrfs_ioctl_defrag_range_args range;
87 while(1) {
88 int c = getopt(ac, av, "vcfs:l:t:");
89 if (c < 0)
90 break;
91 switch(c) {
92 case 'c':
93 compress = 1;
94 break;
95 case 'f':
96 flush = 1;
97 break;
98 case 'v':
99 verbose = 1;
100 break;
101 case 's':
102 start = parse_size(optarg);
103 break;
104 case 'l':
105 len = parse_size(optarg);
106 break;
107 case 't':
108 thresh = parse_size(optarg);
109 break;
110 default:
111 print_usage();
112 return 1;
115 if (ac - optind == 0)
116 print_usage();
118 memset(&range, 0, sizeof(range));
119 range.start = start;
120 range.len = len;
121 range.extent_thresh = thresh;
122 if (compress)
123 range.flags |= BTRFS_DEFRAG_RANGE_COMPRESS;
124 if (flush)
125 range.flags |= BTRFS_DEFRAG_RANGE_START_IO;
127 for (i = optind; i < ac; i++) {
128 fd = open(av[i], O_RDWR);
129 if (fd < 0) {
130 fprintf(stderr, "failed to open %s\n", av[i]);
131 perror("open:");
132 errors++;
133 continue;
135 ret = ioctl(fd, BTRFS_IOC_DEFRAG_RANGE, &range);
136 if (ret) {
137 fprintf(stderr, "ioctl failed on %s ret %d\n",
138 av[i], ret);
139 errors++;
141 close(fd);
143 if (verbose)
144 printf("%s\n", BTRFS_BUILD_VERSION);
145 if (errors) {
146 fprintf(stderr, "total %d failures\n", errors);
147 exit(1);
149 return 0;