btrfs-progs: alias btrfs device delete to btrfs device remove
[platform/upstream/btrfs-progs.git] / cmds-balance.c
index 38a7426..9af218b 100644 (file)
 #include "volumes.h"
 
 #include "commands.h"
+#include "utils.h"
 
 static const char * const balance_cmd_group_usage[] = {
-       "btrfs [filesystem] balance <command> [options] <path>",
-       "btrfs [filesystem] balance <path>",
+       "btrfs balance <command> [options] <path>",
+       "btrfs balance <path>",
        NULL
 };
 
-static const char balance_cmd_group_info[] =
-       "'btrfs filesystem balance' command is deprecated, please use\n"
-       "'btrfs balance start' command instead.";
-
 static int parse_one_profile(const char *profile, u64 *flags)
 {
        if (!strcmp(profile, "raid0")) {
@@ -47,6 +44,10 @@ static int parse_one_profile(const char *profile, u64 *flags)
                *flags |= BTRFS_BLOCK_GROUP_RAID1;
        } else if (!strcmp(profile, "raid10")) {
                *flags |= BTRFS_BLOCK_GROUP_RAID10;
+       } else if (!strcmp(profile, "raid5")) {
+               *flags |= BTRFS_BLOCK_GROUP_RAID5;
+       } else if (!strcmp(profile, "raid6")) {
+               *flags |= BTRFS_BLOCK_GROUP_RAID6;
        } else if (!strcmp(profile, "dup")) {
                *flags |= BTRFS_BLOCK_GROUP_DUP;
        } else if (!strcmp(profile, "single")) {
@@ -62,7 +63,7 @@ static int parse_one_profile(const char *profile, u64 *flags)
 static int parse_profiles(char *profiles, u64 *flags)
 {
        char *this_char;
-       char *save_ptr;
+       char *save_ptr = NULL; /* Satisfy static checkers */
 
        for (this_char = strtok_r(profiles, "|", &save_ptr);
             this_char != NULL;
@@ -131,7 +132,7 @@ static int parse_filters(char *filters, struct btrfs_balance_args *args)
 {
        char *this_char;
        char *value;
-       char *save_ptr;
+       char *save_ptr = NULL; /* Satisfy static checkers */
 
        if (!filters)
                return 0;
@@ -159,7 +160,7 @@ static int parse_filters(char *filters, struct btrfs_balance_args *args)
                                return 1;
                        }
                        if (parse_u64(value, &args->usage) ||
-                           args->usage < 1 || args->usage > 100) {
+                           args->usage > 100) {
                                fprintf(stderr, "Invalid usage argument: %s\n",
                                       value);
                                return 1;
@@ -213,6 +214,18 @@ static int parse_filters(char *filters, struct btrfs_balance_args *args)
                        args->flags |= BTRFS_BALANCE_ARGS_CONVERT;
                } else if (!strcmp(this_char, "soft")) {
                        args->flags |= BTRFS_BALANCE_ARGS_SOFT;
+               } else if (!strcmp(this_char, "limit")) {
+                       if (!value || !*value) {
+                               fprintf(stderr,
+                                       "the limit filter requires an argument\n");
+                               return 1;
+                       }
+                       if (parse_u64(value, &args->limit)) {
+                               fprintf(stderr, "Invalid limit argument: %s\n",
+                                      value);
+                               return 1;
+                       }
+                       args->flags |= BTRFS_BALANCE_ARGS_LIMIT;
                } else {
                        fprintf(stderr, "Unrecognized balance option '%s'\n",
                                this_char);
@@ -247,6 +260,8 @@ static void dump_balance_args(struct btrfs_balance_args *args)
                printf(", vrange=%llu..%llu",
                       (unsigned long long)args->vstart,
                       (unsigned long long)args->vend);
+       if (args->flags & BTRFS_BALANCE_ARGS_LIMIT)
+               printf(", limit=%llu", (unsigned long long)args->limit);
 
        printf("\n");
 }
@@ -289,11 +304,12 @@ static int do_balance(const char *path, struct btrfs_ioctl_balance_args *args,
        int fd;
        int ret;
        int e;
+       DIR *dirstream = NULL;
 
-       fd = open_file_or_dir(path);
+       fd = open_file_or_dir(path, &dirstream);
        if (fd < 0) {
-               fprintf(stderr, "ERROR: can't access to '%s'\n", path);
-               return 12;
+               fprintf(stderr, "ERROR: can't access '%s'\n", path);
+               return 1;
        }
 
        ret = ioctl(fd, BTRFS_IOC_BALANCE_V2, args);
@@ -324,7 +340,7 @@ static int do_balance(const char *path, struct btrfs_ioctl_balance_args *args,
                        if (e != EINPROGRESS)
                                fprintf(stderr, "There may be more info in "
                                        "syslog - try dmesg | tail\n");
-                       ret = 19;
+                       ret = 1;
                }
        } else {
                printf("Done, had to relocate %llu out of %llu chunks\n",
@@ -334,12 +350,12 @@ static int do_balance(const char *path, struct btrfs_ioctl_balance_args *args,
        }
 
 out:
-       close(fd);
+       close_file_or_dir(fd, dirstream);
        return ret;
 }
 
 static const char * const cmd_balance_start_usage[] = {
-       "btrfs [filesystem] balance start [options] <path>",
+       "btrfs balance start [options] <path>",
        "Balance chunks across the devices",
        "Balance and/or convert (change allocation profile of) chunks that",
        "passed all filters in a comma-separated list of filters for a",
@@ -349,7 +365,7 @@ static const char * const cmd_balance_start_usage[] = {
        "",
        "-d[filters]    act on data chunks",
        "-m[filters]    act on metadata chunks",
-       "-s[filetrs]    act on system chunks (only under -f)",
+       "-s[filters]    act on system chunks (only under -f)",
        "-v             be verbose",
        "-f             force reducing of metadata integrity",
        NULL
@@ -369,18 +385,16 @@ static int cmd_balance_start(int argc, char **argv)
 
        optind = 1;
        while (1) {
-               int longindex;
-               static struct option longopts[] = {
+               static const struct option longopts[] = {
                        { "data", optional_argument, NULL, 'd'},
                        { "metadata", optional_argument, NULL, 'm' },
                        { "system", optional_argument, NULL, 's' },
                        { "force", no_argument, NULL, 'f' },
                        { "verbose", no_argument, NULL, 'v' },
-                       { 0, 0, 0, 0 }
+                       { NULL, 0, NULL, 0 }
                };
 
-               int opt = getopt_long(argc, argv, "d::s::m::fv", longopts,
-                                     &longindex);
+               int opt = getopt_long(argc, argv, "d::s::m::fv", longopts, NULL);
                if (opt < 0)
                        break;
 
@@ -471,7 +485,7 @@ static int cmd_balance_start(int argc, char **argv)
 }
 
 static const char * const cmd_balance_pause_usage[] = {
-       "btrfs [filesystem] balance pause <path>",
+       "btrfs balance pause <path>",
        "Pause running balance",
        NULL
 };
@@ -482,33 +496,37 @@ static int cmd_balance_pause(int argc, char **argv)
        int fd;
        int ret;
        int e;
+       DIR *dirstream = NULL;
 
        if (check_argc_exact(argc, 2))
                usage(cmd_balance_pause_usage);
 
        path = argv[1];
 
-       fd = open_file_or_dir(path);
+       fd = open_file_or_dir(path, &dirstream);
        if (fd < 0) {
-               fprintf(stderr, "ERROR: can't access to '%s'\n", path);
-               return 12;
+               fprintf(stderr, "ERROR: can't access '%s'\n", path);
+               return 1;
        }
 
        ret = ioctl(fd, BTRFS_IOC_BALANCE_CTL, BTRFS_BALANCE_CTL_PAUSE);
        e = errno;
-       close(fd);
+       close_file_or_dir(fd, dirstream);
 
        if (ret < 0) {
                fprintf(stderr, "ERROR: balance pause on '%s' failed - %s\n",
                        path, (e == ENOTCONN) ? "Not running" : strerror(e));
-               return 19;
+               if (e == ENOTCONN)
+                       return 2;
+               else
+                       return 1;
        }
 
        return 0;
 }
 
 static const char * const cmd_balance_cancel_usage[] = {
-       "btrfs [filesystem] balance cancel <path>",
+       "btrfs balance cancel <path>",
        "Cancel running or paused balance",
        NULL
 };
@@ -519,33 +537,37 @@ static int cmd_balance_cancel(int argc, char **argv)
        int fd;
        int ret;
        int e;
+       DIR *dirstream = NULL;
 
        if (check_argc_exact(argc, 2))
                usage(cmd_balance_cancel_usage);
 
        path = argv[1];
 
-       fd = open_file_or_dir(path);
+       fd = open_file_or_dir(path, &dirstream);
        if (fd < 0) {
-               fprintf(stderr, "ERROR: can't access to '%s'\n", path);
-               return 12;
+               fprintf(stderr, "ERROR: can't access '%s'\n", path);
+               return 1;
        }
 
        ret = ioctl(fd, BTRFS_IOC_BALANCE_CTL, BTRFS_BALANCE_CTL_CANCEL);
        e = errno;
-       close(fd);
+       close_file_or_dir(fd, dirstream);
 
        if (ret < 0) {
                fprintf(stderr, "ERROR: balance cancel on '%s' failed - %s\n",
                        path, (e == ENOTCONN) ? "Not in progress" : strerror(e));
-               return 19;
+               if (e == ENOTCONN)
+                       return 2;
+               else
+                       return 1;
        }
 
        return 0;
 }
 
 static const char * const cmd_balance_resume_usage[] = {
-       "btrfs [filesystem] balance resume <path>",
+       "btrfs balance resume <path>",
        "Resume interrupted balance",
        NULL
 };
@@ -554,6 +576,7 @@ static int cmd_balance_resume(int argc, char **argv)
 {
        struct btrfs_ioctl_balance_args args;
        const char *path;
+       DIR *dirstream = NULL;
        int fd;
        int ret;
        int e;
@@ -563,10 +586,10 @@ static int cmd_balance_resume(int argc, char **argv)
 
        path = argv[1];
 
-       fd = open_file_or_dir(path);
+       fd = open_file_or_dir(path, &dirstream);
        if (fd < 0) {
-               fprintf(stderr, "ERROR: can't access to '%s'\n", path);
-               return 12;
+               fprintf(stderr, "ERROR: can't access '%s'\n", path);
+               return 1;
        }
 
        memset(&args, 0, sizeof(args));
@@ -574,7 +597,7 @@ static int cmd_balance_resume(int argc, char **argv)
 
        ret = ioctl(fd, BTRFS_IOC_BALANCE_V2, &args);
        e = errno;
-       close(fd);
+       close_file_or_dir(fd, dirstream);
 
        if (ret < 0) {
                if (e == ECANCELED) {
@@ -587,12 +610,15 @@ static int cmd_balance_resume(int argc, char **argv)
                                "failed - %s\n", path,
                                (e == ENOTCONN) ? "Not in progress" :
                                                  "Already running");
-                       return 19;
+                       if (e == ENOTCONN)
+                               return 2;
+                       else
+                               return 1;
                } else {
                        fprintf(stderr,
 "ERROR: error during balancing '%s' - %s\n"
 "There may be more info in syslog - try dmesg | tail\n", path, strerror(e));
-                       return 19;
+                       return 1;
                }
        } else {
                printf("Done, had to relocate %llu out of %llu chunks\n",
@@ -604,17 +630,24 @@ static int cmd_balance_resume(int argc, char **argv)
 }
 
 static const char * const cmd_balance_status_usage[] = {
-       "btrfs [filesystem] balance status [-v] <path>",
+       "btrfs balance status [-v] <path>",
        "Show status of running or paused balance",
        "",
        "-v     be verbose",
        NULL
 };
 
+/* Checks the status of the balance if any
+ * return codes:
+ *   2 : Error failed to know if there is any pending balance
+ *   1 : Successful to know status of a pending balance
+ *   0 : When there is no pending balance or completed
+ */
 static int cmd_balance_status(int argc, char **argv)
 {
        struct btrfs_ioctl_balance_args args;
        const char *path;
+       DIR *dirstream = NULL;
        int fd;
        int verbose = 0;
        int ret;
@@ -622,13 +655,13 @@ static int cmd_balance_status(int argc, char **argv)
 
        optind = 1;
        while (1) {
-               int longindex;
-               static struct option longopts[] = {
+               int opt;
+               static const struct option longopts[] = {
                        { "verbose", no_argument, NULL, 'v' },
-                       { 0, 0, 0, 0}
+                       { NULL, 0, NULL, 0 }
                };
 
-               int opt = getopt_long(argc, argv, "v", longopts, &longindex);
+               opt = getopt_long(argc, argv, "v", longopts, NULL);
                if (opt < 0)
                        break;
 
@@ -646,20 +679,24 @@ static int cmd_balance_status(int argc, char **argv)
 
        path = argv[optind];
 
-       fd = open_file_or_dir(path);
+       fd = open_file_or_dir(path, &dirstream);
        if (fd < 0) {
-               fprintf(stderr, "ERROR: can't access to '%s'\n", path);
-               return 12;
+               fprintf(stderr, "ERROR: can't access '%s'\n", path);
+               return 2;
        }
 
        ret = ioctl(fd, BTRFS_IOC_BALANCE_PROGRESS, &args);
        e = errno;
-       close(fd);
+       close_file_or_dir(fd, dirstream);
 
        if (ret < 0) {
+               if (e == ENOTCONN) {
+                       printf("No balance found on '%s'\n", path);
+                       return 0;
+               }
                fprintf(stderr, "ERROR: balance status on '%s' failed - %s\n",
-                       path, (e == ENOTCONN) ? "Not in progress" : strerror(e));
-               return 19;
+                       path, strerror(e));
+               return 2;
        }
 
        if (args.state & BTRFS_BALANCE_STATE_RUNNING) {
@@ -683,9 +720,12 @@ static int cmd_balance_status(int argc, char **argv)
        if (verbose)
                dump_ioctl_balance_args(&args);
 
-       return 0;
+       return 1;
 }
 
+static const char balance_cmd_group_info[] =
+"balance data accross devices, or change block groups using filters";
+
 const struct cmd_group balance_cmd_group = {
        balance_cmd_group_usage, balance_cmd_group_info, {
                { "start", cmd_balance_start, cmd_balance_start_usage, NULL, 0 },
@@ -693,7 +733,7 @@ const struct cmd_group balance_cmd_group = {
                { "cancel", cmd_balance_cancel, cmd_balance_cancel_usage, NULL, 0 },
                { "resume", cmd_balance_resume, cmd_balance_resume_usage, NULL, 0 },
                { "status", cmd_balance_status, cmd_balance_status_usage, NULL, 0 },
-               { 0, 0, 0, 0, 0 }
+               NULL_CMD_STRUCT
        }
 };