1
0
mirror of https://github.com/Zygo/bees.git synced 2025-06-17 01:56:16 +02:00

workarounds: add workaround for btrfs send

Introduce --workaround options which trade performance or effectiveness to
avoid triggering kernel bugs.

The first such option is --workaround-btrfs-send, which avoids making any
modification to read-only subvols to avoid btrfs send bugs.

Clean up usage message:  no tabs for formatting, split options into
sections by theme.

Make scan mode a non-static data member like all (most?) other options.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
This commit is contained in:
Zygo Blaxell
2018-11-17 00:46:58 -05:00
parent 6c68e81da7
commit 23f3e4ec42
4 changed files with 159 additions and 38 deletions

View File

@ -35,6 +35,7 @@ int bees_log_level = 8;
int
do_cmd_help(char *argv[])
{
// 80col 01234567890123456789012345678901234567890123456789012345678901234567890123456789
cerr << "Usage: " << argv[0] << " [options] fs-root-path [fs-root-path-2...]\n"
"Performs best-effort extent-same deduplication on btrfs.\n"
"\n"
@ -42,25 +43,35 @@ do_cmd_help(char *argv[])
"Other directories will be rejected.\n"
"\n"
"Options:\n"
"\t-h, --help\t\tShow this help\n"
"\t-c, --thread-count\tWorker thread count (default CPU count * factor)\n"
"\t-C, --thread-factor\tWorker thread factor (default " << BEES_DEFAULT_THREAD_FACTOR << ")\n"
"\t-G, --thread-min\t\tMinimum worker thread count with load average target (default 0)\n"
"\t-g, --loadavg-target\t\tTarget load average for worker threads (default is no target)\n"
"\t-m, --scan-mode\t\tScanning mode (0..2, default 0)\n"
"\t-t, --timestamps\tShow timestamps in log output (default)\n"
"\t-T, --no-timestamps\tOmit timestamps in log output\n"
"\t-p, --absolute-paths\tShow absolute paths (default)\n"
"\t-P, --strip-paths\tStrip $CWD from beginning of all paths in the log\n"
"\t-v, --verbose\tSet maximum log level (0..8, default 8)\n"
" -h, --help Show this help\n"
"\n"
"Load management options:\n"
" -c, --thread-count Worker thread count (default CPU count * factor)\n"
" -C, --thread-factor Worker thread factor (default " << BEES_DEFAULT_THREAD_FACTOR << ")\n"
" -G, --thread-min Minimum worker thread count (default 0)\n"
" -g, --loadavg-target Target load average for worker threads (default none)\n"
"\n"
"Filesystem tree traversal options:\n"
" -m, --scan-mode Scanning mode (0..2, default 0)\n"
"\n"
"Workarounds:\n"
" -a, --workaround-btrfs-send Workaround for btrfs send\n"
"\n"
"Logging options:\n"
" -t, --timestamps Show timestamps in log output (default)\n"
" -T, --no-timestamps Omit timestamps in log output\n"
" -p, --absolute-paths Show absolute paths (default)\n"
" -P, --strip-paths Strip $CWD from beginning of all paths in the log\n"
" -v, --verbose Set maximum log level (0..8, default 8)\n"
"\n"
"Optional environment variables:\n"
"\tBEESHOME\tPath to hash table and configuration files\n"
"\t\t\t(default is .beeshome/ in the root of each filesystem).\n"
" BEESHOME Path to hash table and configuration files\n"
" (default is .beeshome/ in the root of each filesystem).\n"
"\n"
"\tBEESSTATUS\tFile to write status to (tmpfs recommended, e.g. /run).\n"
"\t\t\tNo status is written if this variable is unset.\n"
" BEESSTATUS File to write status to (tmpfs recommended, e.g. /run).\n"
" No status is written if this variable is unset.\n"
"\n"
// 80col 01234567890123456789012345678901234567890123456789012345678901234567890123456789
<< endl;
return 0;
}
@ -657,26 +668,47 @@ bees_main(int argc, char *argv[])
unsigned thread_count = 0;
unsigned thread_min = 0;
double load_target = 0;
bool workaround_btrfs_send = false;
// Configure getopt_long
static const struct option long_options[] = {
{ "thread-factor", required_argument, NULL, 'C' },
{ "thread-min", required_argument, NULL, 'G' },
{ "strip-paths", no_argument, NULL, 'P' },
{ "no-timestamps", no_argument, NULL, 'T' },
{ "workaround-btrfs-send", no_argument, NULL, 'a' },
{ "thread-count", required_argument, NULL, 'c' },
{ "loadavg-target", required_argument, NULL, 'g' },
{ "help", no_argument, NULL, 'h' },
{ "scan-mode", required_argument, NULL, 'm' },
{ "absolute-paths", no_argument, NULL, 'p' },
{ "timestamps", no_argument, NULL, 't' },
{ "verbose", required_argument, NULL, 'v' },
{ 0, 0, 0, 0 },
};
// Build getopt_long's short option list from the long_options table.
// While we're at it, make sure we didn't duplicate any options.
string getopt_list;
set<decltype(option::val)> option_vals;
for (const struct option *op = long_options; op->val; ++op) {
THROW_CHECK1(runtime_error, op->val, !option_vals.count(op->val));
option_vals.insert(op->val);
if ((op->val & 0xff) != op->val) {
continue;
}
getopt_list += op->val;
if (op->has_arg == required_argument) {
getopt_list += ':';
}
}
// Parse options
int c;
while (1) {
int option_index = 0;
static const struct option long_options[] = {
{ "thread-factor", required_argument, NULL, 'C' },
{ "thread-min", required_argument, NULL, 'G' },
{ "strip-paths", no_argument, NULL, 'P' },
{ "no-timestamps", no_argument, NULL, 'T' },
{ "thread-count", required_argument, NULL, 'c' },
{ "loadavg-target", required_argument, NULL, 'g' },
{ "help", no_argument, NULL, 'h' },
{ "scan-mode", required_argument, NULL, 'm' },
{ "absolute-paths", no_argument, NULL, 'p' },
{ "timestamps", no_argument, NULL, 't' },
{ "verbose", required_argument, NULL, 'v' },
};
c = getopt_long(argc, argv, "C:G:PTc:hg:m:ptv:", long_options, &option_index);
c = getopt_long(argc, argv, getopt_list.c_str(), long_options, &option_index);
if (-1 == c) {
break;
}
@ -695,6 +727,9 @@ bees_main(int argc, char *argv[])
case 'T':
chatter_prefix_timestamp = false;
break;
case 'a':
workaround_btrfs_send = true;
break;
case 'c':
thread_count = stoul(optarg);
break;
@ -702,7 +737,7 @@ bees_main(int argc, char *argv[])
load_target = stod(optarg);
break;
case 'm':
BeesRoots::set_scan_mode(static_cast<BeesRoots::ScanMode>(stoul(optarg)));
bc->roots()->set_scan_mode(static_cast<BeesRoots::ScanMode>(stoul(optarg)));
break;
case 'p':
crucible::set_relative_path("");
@ -763,6 +798,9 @@ bees_main(int argc, char *argv[])
BEESLOGNOTICE("setting worker thread pool maximum size to " << thread_count);
TaskMaster::set_thread_count(thread_count);
// Workaround for btrfs send
bc->roots()->set_workaround_btrfs_send(workaround_btrfs_send);
// Create a context and start crawlers
bool did_subscription = false;
while (optind < argc) {