Add online resizing ioctls
authorChris Mason <chris.mason@oracle.com>
Fri, 21 Dec 2007 21:25:35 +0000 (16:25 -0500)
committerDavid Woodhouse <dwmw2@hera.kernel.org>
Fri, 21 Dec 2007 21:25:35 +0000 (16:25 -0500)
btrfsctl -r size mount_point

btrfsctl.c
ioctl.h
mkfs.c

index 4dfc42b..22f253a 100644 (file)
@@ -41,7 +41,12 @@ static inline int ioctl(int fd, int define, void *arg) { return 0; }
 
 void print_usage(void)
 {
-       printf("usage: btrfsctl [ -s snapshot_name ] dir\n");
+       printf("usage: btrfsctl [ -s name ] [-d] [-r size] file_or_dir\n");
+       printf("\t-d filename defragments one file\n");
+       printf("\t-d directory defragments the entire Btree\n");
+       printf("\t-s snap_name existing_subvol creates a new snapshot\n");
+       printf("\t-s snap_name tree_root creates a new subvolume\n");
+       printf("\t-r [+-]size[gkm] resize the FS\n");
        exit(1);
 }
 
@@ -79,10 +84,22 @@ int main(int ac, char **av)
                        command = BTRFS_IOC_SNAP_CREATE;
                } else if (strcmp(av[i], "-d") == 0) {
                        if (i >= ac - 1) {
-                               fprintf(stderr, "-d requires an arg");
+                               fprintf(stderr, "-d requires an arg\n");
                                print_usage();
                        }
                        command = BTRFS_IOC_DEFRAG;
+               } else if (strcmp(av[i], "-r") == 0) {
+                       if (i >= ac - 1) {
+                               fprintf(stderr, "-r requires an arg\n");
+                               print_usage();
+                       }
+                       name = av[i + 1];
+                       len = strlen(name);
+                       if (len == 0 || len >= BTRFS_VOL_NAME_MAX) {
+                               fprintf(stderr, "-r size too long\n");
+                               exit(1);
+                       }
+                       command = BTRFS_IOC_RESIZE;
                }
        }
        if (command == 0) {
diff --git a/ioctl.h b/ioctl.h
index 8bc47de..8c62906 100644 (file)
--- a/ioctl.h
+++ b/ioctl.h
@@ -30,4 +30,6 @@ struct btrfs_ioctl_vol_args {
                                   struct btrfs_ioctl_vol_args)
 #define BTRFS_IOC_DEFRAG _IOW(BTRFS_IOCTL_MAGIC, 2, \
                                   struct btrfs_ioctl_vol_args)
+#define BTRFS_IOC_RESIZE _IOW(BTRFS_IOCTL_MAGIC, 3, \
+                                  struct btrfs_ioctl_vol_args)
 #endif
diff --git a/mkfs.c b/mkfs.c
index b49b088..57c54b9 100644 (file)
--- a/mkfs.c
+++ b/mkfs.c
@@ -29,6 +29,7 @@
 #include <unistd.h>
 #include <uuid/uuid.h>
 #include <linux/fs.h>
+#include <ctype.h>
 #include "kerncompat.h"
 #include "ctree.h"
 #include "disk-io.h"
 static inline int ioctl(int fd, int define, u64 *size) { return 0; }
 #endif
 
+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 atol(s) * mult;
+}
+
 static int __make_root_dir(struct btrfs_trans_handle *trans,
                           struct btrfs_root *root, u64 objectid)
 {
@@ -367,13 +394,13 @@ int main(int ac, char **av)
                        break;
                switch(c) {
                        case 'l':
-                               leafsize = atol(optarg);
+                               leafsize = parse_size(optarg);
                                break;
                        case 'n':
-                               nodesize = atol(optarg);
+                               nodesize = parse_size(optarg);
                                break;
                        case 's':
-                               stripesize = atol(optarg);
+                               stripesize = parse_size(optarg);
                                break;
                        default:
                                print_usage();
@@ -391,7 +418,7 @@ int main(int ac, char **av)
        if (ac >= 1) {
                file = av[optind];
                if (ac == 2) {
-                       block_count = atol(av[optind + 1]);
+                       block_count = parse_size(av[optind + 1]);
                        if (!block_count) {
                                fprintf(stderr, "error finding block count\n");
                                exit(1);
@@ -416,13 +443,14 @@ int main(int ac, char **av)
                        fprintf(stderr, "unable to find %s size\n", file);
                        exit(1);
                }
-               block_count /= sectorsize;
        }
-       if (block_count < 256) {
+       block_count /= sectorsize;
+       block_count *= sectorsize;
+
+       if (block_count < 256 * 1024 * 1024) {
                fprintf(stderr, "device %s is too small\n", file);
                exit(1);
        }
-       block_count = block_count * sectorsize;
        memset(buf, 0, sectorsize);
        for(i = 0; i < 64; i++) {
                ret = write(fd, buf, sectorsize);