On Mon, May 2, 2016 at 4:33 AM, David Sterba <dste...@suse.com> wrote: > A short delay with a warning before starting a full balance should > improve usability. We have been getting reports from people who run full > balance after following some random advice and then get surprised by the > performance impact. > > The countdown is done even when run from scripts, but as the whole > balance takes significanly more time, this shouldn't be an issue. > > Signed-off-by: David Sterba <dste...@suse.com> > --- > Documentation/btrfs-balance.asciidoc | 6 ++++ > cmds-balance.c | 65 > ++++++++++++++++++++++++++++++------ > 2 files changed, 60 insertions(+), 11 deletions(-) > > diff --git a/Documentation/btrfs-balance.asciidoc > b/Documentation/btrfs-balance.asciidoc > index 8b5df96ad41f..7df40b9c6f49 100644 > --- a/Documentation/btrfs-balance.asciidoc > +++ b/Documentation/btrfs-balance.asciidoc > @@ -67,6 +67,12 @@ resume interrupted balance > start the balance operation according to the specified filters, no filters > will rewrite the entire filesystem. The process runs in the foreground. > + > +NOTE: the balance command without filters will basically rewrite everything > +in the filesystem. The run time is potentially very long, depending on the > +filesystem size. To prevent starting a full balance by accident, the user is > +warned and has a few seconds to cancel the operation before it starts. The > +warning and delay can be skipped with '--full-balance' option. > ++ > `Options` > + > -d[<filters>]:::: > diff --git a/cmds-balance.c b/cmds-balance.c > index 33f91e41134e..5f05f603d4c8 100644 > --- a/cmds-balance.c > +++ b/cmds-balance.c > @@ -417,8 +417,13 @@ static int do_balance_v1(int fd) > return ret; > } > > +enum { > + BALANCE_START_FILTERS = 1 << 0, > + BALANCE_START_NOWARN = 1 << 1 > +}; > + > static int do_balance(const char *path, struct btrfs_ioctl_balance_args > *args, > - int nofilters) > + unsigned flags) > { > int fd; > int ret; > @@ -429,6 +434,24 @@ static int do_balance(const char *path, struct > btrfs_ioctl_balance_args *args, > if (fd < 0) > return 1; > > + if (!(flags & BALANCE_START_FILTERS) && !(flags & > BALANCE_START_NOWARN)) { > + int delay = 10; > + > + printf("WARNING:\n\n"); > + printf("\tFull balance without filters requested. This > operation is very\n"); > + printf("\tintense and takes potentially very long. It is > recommended to\n"); > + printf("\tuse the balance filters to narrow down the balanced > data.\n"); > + printf("\tUse 'btrfs balance start --full-balance' option to > skip this\n"); > + printf("\twarning. The operation will start in %d > seconds.\n", delay); > + printf("\tUse Ctrl-C to stop it.\n"); > + while (delay) { > + sleep(1); > + printf("%2d", delay--); > + fflush(stdout); > + }
Shouldn't the sleep be after the fflush? > + printf("\nStarting balance without any filters.\n"); > + } > + > ret = ioctl(fd, BTRFS_IOC_BALANCE_V2, args); > e = errno; > > @@ -438,7 +461,7 @@ static int do_balance(const char *path, struct > btrfs_ioctl_balance_args *args, > * old one. But, the old one doesn't know any filters, so > * don't fall back if they tried to use the fancy new things > */ > - if (e == ENOTTY && nofilters) { > + if (e == ENOTTY && !(flags & BALANCE_START_FILTERS)) { > ret = do_balance_v1(fd); > if (ret == 0) > goto out; > @@ -477,13 +500,16 @@ static const char * const cmd_balance_start_usage[] = { > "passed all filters in a comma-separated list of filters for a", > "particular chunk type. If filter list is not given balance all", > "chunks of that type. In case none of the -d, -m or -s options is", > - "given balance all chunks in a filesystem.", > + "given balance all chunks in a filesystem. This is potentially", > + "long operation and the user is warned before this start, with", > + "a delay to stop it.", > "", > "-d[filters] act on data chunks", > "-m[filters] act on metadata chunks", > "-s[filters] act on system chunks (only under -f)", > "-v be verbose", > "-f force reducing of metadata integrity", > + "--full-balance do not print warning and do not delay start", > NULL > }; > > @@ -494,19 +520,22 @@ static int cmd_balance_start(int argc, char **argv) > &args.meta, NULL }; > int force = 0; > int verbose = 0; > - int nofilters = 1; > + unsigned start_flags = 0; > int i; > > memset(&args, 0, sizeof(args)); > > optind = 1; > while (1) { > + enum { GETOPT_VAL_FULL_BALANCE = 256 }; > 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' }, > + { "full-balance", no_argument, NULL, > + GETOPT_VAL_FULL_BALANCE }, > { NULL, 0, NULL, 0 } > }; > > @@ -516,21 +545,21 @@ static int cmd_balance_start(int argc, char **argv) > > switch (opt) { > case 'd': > - nofilters = 0; > + start_flags |= BALANCE_START_FILTERS; > args.flags |= BTRFS_BALANCE_DATA; > > if (parse_filters(optarg, &args.data)) > return 1; > break; > case 's': > - nofilters = 0; > + start_flags |= BALANCE_START_FILTERS; > args.flags |= BTRFS_BALANCE_SYSTEM; > > if (parse_filters(optarg, &args.sys)) > return 1; > break; > case 'm': > - nofilters = 0; > + start_flags |= BALANCE_START_FILTERS; > args.flags |= BTRFS_BALANCE_METADATA; > > if (parse_filters(optarg, &args.meta)) > @@ -542,6 +571,9 @@ static int cmd_balance_start(int argc, char **argv) > case 'v': > verbose = 1; > break; > + case GETOPT_VAL_FULL_BALANCE: > + start_flags |= BALANCE_START_NOWARN; > + break; > default: > usage(cmd_balance_start_usage); > } > @@ -567,7 +599,7 @@ static int cmd_balance_start(int argc, char **argv) > sizeof(struct btrfs_balance_args)); > } > > - if (nofilters) { > + if (!(start_flags & BALANCE_START_FILTERS)) { > /* relocate everything - no filters */ > args.flags |= BTRFS_BALANCE_TYPE_MASK; > } > @@ -595,7 +627,7 @@ static int cmd_balance_start(int argc, char **argv) > if (verbose) > dump_ioctl_balance_args(&args); > > - return do_balance(argv[optind], &args, nofilters); > + return do_balance(argv[optind], &args, start_flags); > } > > static const char * const cmd_balance_pause_usage[] = { > @@ -833,6 +865,16 @@ static int cmd_balance_status(int argc, char **argv) > return 1; > } > > +static int cmd_balance_full(int argc, char **argv) > +{ > + struct btrfs_ioctl_balance_args args; > + > + memset(&args, 0, sizeof(args)); > + args.flags |= BTRFS_BALANCE_TYPE_MASK; > + > + return do_balance(argv[1], &args, BALANCE_START_NOWARN); > +} > + > static const char balance_cmd_group_info[] = > "balance data accross devices, or change block groups using filters"; > > @@ -843,20 +885,21 @@ 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 }, > + { "--full-balance", cmd_balance_full, NULL, NULL, 1 }, > NULL_CMD_STRUCT > } > }; > > int cmd_balance(int argc, char **argv) > { > - if (argc == 2) { > + if (argc == 2 && strcmp("start", argv[1]) != 0) { > /* old 'btrfs filesystem balance <path>' syntax */ > struct btrfs_ioctl_balance_args args; > > memset(&args, 0, sizeof(args)); > args.flags |= BTRFS_BALANCE_TYPE_MASK; > > - return do_balance(argv[1], &args, 1); > + return do_balance(argv[1], &args, 0); > } > > return handle_command_group(&balance_cmd_group, argc, argv); > -- > 2.7.1 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in > the body of a message to majord...@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html