This patch makes a balance operation fork and detach from the current terminal, to run the userspace side of the balance in the background.
Introduce a --wait switch so that a synchronous balance can be done if the user requires. Signed-off-by: Hugo Mills <h...@carfax.org.uk> --- btrfs.c | 8 ++++---- btrfs_cmds.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++-- man/btrfs.8.in | 19 ++++++++++--------- 3 files changed, 64 insertions(+), 15 deletions(-) diff --git a/btrfs.c b/btrfs.c index 93f7886..7b42658 100644 --- a/btrfs.c +++ b/btrfs.c @@ -91,12 +91,12 @@ static struct Command commands[] = { "filesystem df", "<path>\n" "Show space usage information for a mount point\n." }, - { do_balance, 1, - "filesystem balance", "<path>\n" + { do_balance, -1, + "filesystem balance", "[-w|--wait] <path>\n" "Balance the chunks across the device." }, - { do_balance, 1, - "balance start", "<path>\n" + { do_balance, -1, + "balance start", "[-w|--wait] <path>\n" "Synonym for \"btrfs filesystem balance\"." }, { do_balance_progress, -1, diff --git a/btrfs_cmds.c b/btrfs_cmds.c index d246a8b..fadcb4f 100644 --- a/btrfs_cmds.c +++ b/btrfs_cmds.c @@ -754,12 +754,41 @@ int do_add_volume(int nargs, char **args) } +const struct option balance_options[] = { + { "wait", 0, NULL, 'w' }, + { NULL, 0, NULL, 0 } +}; + int do_balance(int argc, char **argv) { - int fdmnt, ret=0; + int background = 1; struct btrfs_ioctl_vol_args args; - char *path = argv[1]; + char *path; + int ttyfd; + + optind = 1; + while(1) { + int c = getopt_long(argc, argv, "w", balance_options, NULL); + if (c < 0) + break; + switch(c) { + case 'w': + background = 0; + break; + default: + fprintf(stderr, "Invalid arguments for balance\n"); + free(argv); + return 1; + } + } + + if(optind >= argc) { + fprintf(stderr, "No filesystem path given for balance\n"); + return 1; + } + + path = argv[optind]; fdmnt = open_file_or_dir(path); if (fdmnt < 0) { @@ -767,6 +796,25 @@ int do_balance(int argc, char **argv) return 12; } + if (background) { + int pid = fork(); + if (pid == 0) { + /* We're in the child, and can run in the background */ + ttyfd = open("/dev/tty", O_RDWR); + if (ttyfd > 0) + ioctl(ttyfd, TIOCNOTTY, 0); + /* Fall through to the BTRFS_IOC_BALANCE ioctl */ + } else if (pid > 0) { + /* We're in the parent, and the fork succeeded */ + printf("Background balance started\n"); + return 0; + } else { + /* We're in the parent, and the fork failed */ + fprintf(stderr, "ERROR: can't start background process -- %s\n", + strerror(errno)); + } + } + memset(&args, 0, sizeof(args)); ret = ioctl(fdmnt, BTRFS_IOC_BALANCE, &args); close(fdmnt); diff --git a/man/btrfs.8.in b/man/btrfs.8.in index d7fab80..95e39c3 100644 --- a/man/btrfs.8.in +++ b/man/btrfs.8.in @@ -23,13 +23,15 @@ btrfs \- control a btrfs filesystem .PP \fBbtrfs\fP \fBdevice scan\fP\fI [<device> [<device>..]]\fP .PP +\fBbtrfs\fP \fBbalance start\fP [\fB-w\fP|\fB--wait\fP] \fI<path>\fP +.PP \fBbtrfs\fP \fBbalance progress\fP [\fB-m\fP|\fB--monitor\fP] \fI<path>\fP .PP \fBbtrfs\fP \fBbalance cancel\fP \fI<path>\fP .PP \fBbtrfs\fP \fBdevice show\fP\fI <dev>|<label> [<dev>|<label>...]\fP .PP -\fBbtrfs\fP \fBdevice balance\fP\fI <path> \fP +\fBbtrfs\fP \fBfilesystem balance\fP [\fB-w\fP|\fB--wait\fP] \fI<path>\fP .PP \fBbtrfs\fP \fBdevice add\fP\fI <dev> [<dev>..] <path> \fP .PP @@ -147,20 +149,19 @@ Show the btrfs filesystem with some additional info. If no UUID or label is passed, \fBbtrfs\fR show info of all the btrfs filesystem. .TP -\fBdevice balance\fR \fI<path>\fR -Balance the chunks of the filesystem identified by \fI<path>\fR -across the devices. +\fBdevice balance\fR [\fB-w\fP|\fB--wait\fP] \fI<path>\fR + +\fBbalance start\fR [\fB-w\fP|\fB--wait\fP] \fI<path>\fR + +Balance the chunks of the filesystem identified by \fI<path>\fR across +the devices. The process runs in the background. Use \fB--wait\fP to +wait in the foreground for completion of the balance. .TP \fBdevice add\fR\fI <dev> [<dev>..] <path>\fR Add device(s) to the filesystem identified by \fI<path>\fR. .TP -.SS -\fBdevice balance \fI<path>\fP -Balance the chunks of the filesystem identified by \fI<path>\fP -across the devices. - \fBdevice delete\fR\fI <dev> [<dev>..] <path>\fR Remove device(s) from a filesystem identified by \fI<path>\fR. .PP -- 1.7.2.5 -- 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