btrfs-progs: add option to run balance as daemon

Currently, balance operations are run synchronously in the foreground.
This is nice for interactive management, but is kind of crappy when you
start looking at automation and similar things.

This patch adds an option to `btrfs balance start` to tell it to
daemonize prior to running the balance operation, thus allowing us to
preform balances asynchronously.  The two biggest use cases I have for
this are starting a balance on a remote server without establishing a
full shell session, and being able to background the balance in a
recovery shell (which usually has no job control) so I can still get
progress information.

Because it simply daemonizes prior to calling the balance ioctl, this
doesn't actually need any kernel support.

Signed-off-by: Austin S. Hemmelgarn <ahferroin7@gmail.com>
Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
Austin S. Hemmelgarn 2016-06-21 11:16:59 -04:00 committed by David Sterba
parent 1d6c7cb725
commit fe520b5cdc
2 changed files with 43 additions and 1 deletions

View File

@ -104,6 +104,8 @@ act on system chunks (requires '-f'), see `FILTERS` section for details about 'f
be verbose and print balance filter arguments be verbose and print balance filter arguments
-f:::: -f::::
force reducing of metadata integrity, eg. when going from 'raid1' to 'single' force reducing of metadata integrity, eg. when going from 'raid1' to 'single'
--background::::
run the balance operation asynchronously in the background
*status* [-v] <path>:: *status* [-v] <path>::
Show status of running or paused balance. Show status of running or paused balance.

View File

@ -20,6 +20,9 @@
#include <unistd.h> #include <unistd.h>
#include <getopt.h> #include <getopt.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h> #include <errno.h>
#include "kerncompat.h" #include "kerncompat.h"
@ -507,6 +510,7 @@ static const char * const cmd_balance_start_usage[] = {
"-v be verbose", "-v be verbose",
"-f force reducing of metadata integrity", "-f force reducing of metadata integrity",
"--full-balance do not print warning and do not delay start", "--full-balance do not print warning and do not delay start",
"--background run the balance as a background process",
NULL NULL
}; };
@ -517,13 +521,15 @@ static int cmd_balance_start(int argc, char **argv)
&args.meta, NULL }; &args.meta, NULL };
int force = 0; int force = 0;
int verbose = 0; int verbose = 0;
int background = 0;
unsigned start_flags = 0; unsigned start_flags = 0;
int i; int i;
memset(&args, 0, sizeof(args)); memset(&args, 0, sizeof(args));
while (1) { while (1) {
enum { GETOPT_VAL_FULL_BALANCE = 256 }; enum { GETOPT_VAL_FULL_BALANCE = 256,
GETOPT_VAL_BACKGROUND = 257 };
static const struct option longopts[] = { static const struct option longopts[] = {
{ "data", optional_argument, NULL, 'd'}, { "data", optional_argument, NULL, 'd'},
{ "metadata", optional_argument, NULL, 'm' }, { "metadata", optional_argument, NULL, 'm' },
@ -532,6 +538,8 @@ static int cmd_balance_start(int argc, char **argv)
{ "verbose", no_argument, NULL, 'v' }, { "verbose", no_argument, NULL, 'v' },
{ "full-balance", no_argument, NULL, { "full-balance", no_argument, NULL,
GETOPT_VAL_FULL_BALANCE }, GETOPT_VAL_FULL_BALANCE },
{ "background", no_argument, NULL,
GETOPT_VAL_BACKGROUND },
{ NULL, 0, NULL, 0 } { NULL, 0, NULL, 0 }
}; };
@ -570,6 +578,9 @@ static int cmd_balance_start(int argc, char **argv)
case GETOPT_VAL_FULL_BALANCE: case GETOPT_VAL_FULL_BALANCE:
start_flags |= BALANCE_START_NOWARN; start_flags |= BALANCE_START_NOWARN;
break; break;
case GETOPT_VAL_BACKGROUND:
background = 1;
break;
default: default:
usage(cmd_balance_start_usage); usage(cmd_balance_start_usage);
} }
@ -622,6 +633,35 @@ static int cmd_balance_start(int argc, char **argv)
args.flags |= BTRFS_BALANCE_FORCE; args.flags |= BTRFS_BALANCE_FORCE;
if (verbose) if (verbose)
dump_ioctl_balance_args(&args); dump_ioctl_balance_args(&args);
if (background) {
switch (fork()) {
case (-1):
error("unable to fork to run balance in background");
return 1;
case (0):
setsid();
switch(fork()) {
case (-1):
error(
"unable to fork to run balance in background");
exit(1);
case (0):
chdir("/");
close(0);
close(1);
close(2);
open("/dev/null", O_RDONLY);
open("/dev/null", O_WRONLY);
open("/dev/null", O_WRONLY);
break;
default:
exit(0);
}
break;
default:
exit(0);
}
}
return do_balance(argv[optind], &args, start_flags); return do_balance(argv[optind], &args, start_flags);
} }