File 2000-btrfs-full-balance-warning.diff of Package btrfsprogs

Index: btrfs-progs-v4.3/Documentation/btrfs-balance.asciidoc
===================================================================
--- btrfs-progs-v4.3.orig/Documentation/btrfs-balance.asciidoc
+++ btrfs-progs-v4.3/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
+int 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>]::::
Index: btrfs-progs-v4.3/cmds-balance.c
===================================================================
--- btrfs-progs-v4.3.orig/cmds-balance.c
+++ btrfs-progs-v4.3/cmds-balance.c
@@ -383,8 +383,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;
@@ -395,6 +400,24 @@ static int do_balance(const char *path,
 	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 printf will start in %d seconds.\n", delay);
+		printf("\tUse Ctrl-C to stop it.\n");
+		while (delay) {
+			sleep(1);
+			printf("%2d", delay--);
+			fflush(stdout);
+		}
+		printf("\nStarting balance without any filters.\n");
+	}
+
 	ret = ioctl(fd, BTRFS_IOC_BALANCE_V2, args);
 	e = errno;
 
@@ -404,7 +427,7 @@ static int do_balance(const char *path,
 		 * 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;
@@ -444,13 +467,16 @@ static const char * const cmd_balance_st
 	"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
 };
 
@@ -461,19 +487,22 @@ static int cmd_balance_start(int argc, c
 						&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 }
 		};
 
@@ -483,21 +512,21 @@ static int cmd_balance_start(int argc, c
 
 		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))
@@ -509,6 +538,9 @@ static int cmd_balance_start(int argc, c
 		case 'v':
 			verbose = 1;
 			break;
+		case GETOPT_VAL_FULL_BALANCE:
+			start_flags |= BALANCE_START_NOWARN;
+			break;
 		default:
 			usage(cmd_balance_start_usage);
 		}
@@ -534,7 +566,7 @@ static int cmd_balance_start(int argc, c
 			sizeof(struct btrfs_balance_args));
 	}
 
-	if (nofilters) {
+	if (!(start_flags & BALANCE_START_FILTERS)) {
 		/* relocate everything - no filters */
 		args.flags |= BTRFS_BALANCE_TYPE_MASK;
 	}
@@ -564,7 +596,7 @@ static int cmd_balance_start(int argc, c
 	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[] = {
@@ -798,6 +830,16 @@ static int cmd_balance_status(int argc,
 	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";
 
@@ -808,20 +850,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);
openSUSE Build Service is sponsored by