summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile5
-rw-r--r--btrfs-defrag.c151
-rw-r--r--ioctl.h32
3 files changed, 185 insertions, 3 deletions
diff --git a/Makefile b/Makefile
index f2a9d41a..10002681 100644
--- a/Makefile
+++ b/Makefile
@@ -17,7 +17,7 @@ bindir = $(prefix)/bin
LIBS=-luuid
progs = btrfsctl mkfs.btrfs btrfs-debug-tree btrfs-show btrfs-vol btrfsck \
- btrfs-map-logical btrfs-list
+ btrfs-map-logical btrfs-list btrfs-defrag
# make C=1 to enable sparse
ifdef C
@@ -39,6 +39,9 @@ version:
btrfs-list: $(objects) btrfs-list.o
gcc $(CFLAGS) -o btrfs-list btrfs-list.o $(objects) $(LDFLAGS) $(LIBS)
+btrfs-defrag: $(objects) btrfs-defrag.o
+ gcc $(CFLAGS) -o btrfs-defrag btrfs-defrag.o $(objects) $(LDFLAGS) $(LIBS)
+
btrfsctl: $(objects) btrfsctl.o
gcc $(CFLAGS) -o btrfsctl btrfsctl.o $(objects) $(LDFLAGS) $(LIBS)
diff --git a/btrfs-defrag.c b/btrfs-defrag.c
new file mode 100644
index 00000000..9aab3ba4
--- /dev/null
+++ b/btrfs-defrag.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2010 Oracle. 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 v2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will 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 to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 021110-1307, USA.
+ */
+
+#ifndef __CHECKER__
+#include <sys/ioctl.h>
+#include <sys/mount.h>
+#include "ioctl.h"
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <libgen.h>
+#include <getopt.h>
+#include "kerncompat.h"
+#include "ctree.h"
+#include "transaction.h"
+#include "utils.h"
+#include "version.h"
+
+static u64 parse_size(char *s)
+{
+ int len = strlen(s);
+ char c;
+ u64 mult = 1;
+
+ if (!isdigit(s[len - 1])) {
+ c = tolower(s[len - 1]);
+ switch (c) {
+ case 'g':
+ mult *= 1024;
+ case 'm':
+ mult *= 1024;
+ case 'k':
+ mult *= 1024;
+ case 'b':
+ break;
+ default:
+ fprintf(stderr, "Unknown size descriptor %c\n", c);
+ exit(1);
+ }
+ s[len - 1] = '\0';
+ }
+ return atoll(s) * mult;
+}
+
+static void print_usage(void)
+{
+ printf("usage: btrfs-defrag [-c] [-f] [-s start] [-l len] "
+ "[-t threshold] file ...\n");
+ exit(1);
+}
+
+int main(int ac, char **av)
+{
+ int fd;
+ int compress = 0;
+ int flush = 0;
+ u64 start = 0;
+ u64 len = (u64)-1;
+ u32 thresh = 0;
+ int i;
+ int errors = 0;
+ int ret = 0;
+ int verbose = 0;
+ struct btrfs_ioctl_defrag_range_args range;
+
+ while(1) {
+ int c = getopt(ac, av, "vcfs:l:t:");
+ if (c < 0)
+ break;
+ switch(c) {
+ case 'c':
+ compress = 1;
+ break;
+ case 'f':
+ flush = 1;
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ case 's':
+ start = parse_size(optarg);
+ break;
+ case 'l':
+ len = parse_size(optarg);
+ break;
+ case 't':
+ thresh = parse_size(optarg);
+ break;
+ default:
+ print_usage();
+ return 1;
+ }
+ }
+ if (ac - optind == 0)
+ print_usage();
+
+ memset(&range, 0, sizeof(range));
+ range.start = start;
+ range.len = len;
+ range.extent_thresh = thresh;
+ if (compress)
+ range.flags |= BTRFS_DEFRAG_RANGE_COMPRESS;
+ if (flush)
+ range.flags |= BTRFS_DEFRAG_RANGE_START_IO;
+
+ for (i = optind; i < ac; i++) {
+ fd = open(av[i], O_RDWR);
+ if (fd < 0) {
+ fprintf(stderr, "failed to open %s\n", av[i]);
+ perror("open:");
+ errors++;
+ continue;
+ }
+ ret = ioctl(fd, BTRFS_IOC_DEFRAG_RANGE, &range);
+ if (ret) {
+ fprintf(stderr, "ioctl failed on %s ret %d\n",
+ av[i], ret);
+ errors++;
+ }
+ close(fd);
+ }
+ if (verbose)
+ printf("%s\n", BTRFS_BUILD_VERSION);
+ if (errors) {
+ fprintf(stderr, "total %d failures\n", errors);
+ exit(1);
+ }
+ return 0;
+}
+
diff --git a/ioctl.h b/ioctl.h
index 6a4a2d14..97130989 100644
--- a/ioctl.h
+++ b/ioctl.h
@@ -92,6 +92,34 @@ struct btrfs_ioctl_ino_lookup_args {
char name[BTRFS_INO_LOOKUP_PATH_MAX];
};
+/* flags for the defrag range ioctl */
+#define BTRFS_DEFRAG_RANGE_COMPRESS 1
+#define BTRFS_DEFRAG_RANGE_START_IO 2
+
+struct btrfs_ioctl_defrag_range_args {
+ /* start of the defrag operation */
+ __u64 start;
+
+ /* number of bytes to defrag, use (u64)-1 to say all */
+ __u64 len;
+
+ /*
+ * flags for the operation, which can include turning
+ * on compression for this one defrag
+ */
+ __u64 flags;
+
+ /*
+ * any extent bigger than this will be considered
+ * already defragged. Use 0 to take the kernel default
+ * Use 1 to say every single extent must be rewritten
+ */
+ __u32 extent_thresh;
+
+ /* spare for later */
+ __u32 unused[5];
+};
+
#define BTRFS_IOC_SNAP_CREATE _IOW(BTRFS_IOCTL_MAGIC, 1, \
struct btrfs_ioctl_vol_args)
#define BTRFS_IOC_DEFRAG _IOW(BTRFS_IOCTL_MAGIC, 2, \
@@ -118,10 +146,10 @@ struct btrfs_ioctl_ino_lookup_args {
/* 13 is for CLONE_RANGE */
#define BTRFS_IOC_SUBVOL_CREATE _IOW(BTRFS_IOCTL_MAGIC, 14, \
struct btrfs_ioctl_vol_args)
-
#define BTRFS_IOC_SNAP_DESTROY _IOW(BTRFS_IOCTL_MAGIC, 15, \
struct btrfs_ioctl_vol_args)
-
+#define BTRFS_IOC_DEFRAG_RANGE _IOW(BTRFS_IOCTL_MAGIC, 16, \
+ struct btrfs_ioctl_defrag_range_args)
#define BTRFS_IOC_TREE_SEARCH _IOWR(BTRFS_IOCTL_MAGIC, 17, \
struct btrfs_ioctl_search_args)
#define BTRFS_IOC_INO_LOOKUP _IOWR(BTRFS_IOCTL_MAGIC, 18, \