summaryrefslogtreecommitdiff
path: root/src/readahead/readahead.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2012-06-21 23:53:20 +0200
committerLennart Poettering <lennart@poettering.net>2012-06-21 23:53:20 +0200
commit87ce22cc0d097d9cd0297d0141eadba6c573c299 (patch)
tree8b7831ad915705a9ee67aa2e6defdc58dc3e9a9d /src/readahead/readahead.c
parentb4bdfefac3fcf633aa0700a981d854cc49a9725b (diff)
readahead: merge three binaries into one
since the binaries share much of the same code and we better load only one binary instead of two from disk at early boot let's merge the three readahead binaries into one. This also allows us to drop a lot of duplicated code.
Diffstat (limited to 'src/readahead/readahead.c')
-rw-r--r--src/readahead/readahead.c158
1 files changed, 158 insertions, 0 deletions
diff --git a/src/readahead/readahead.c b/src/readahead/readahead.c
new file mode 100644
index 000000000..abeecc763
--- /dev/null
+++ b/src/readahead/readahead.c
@@ -0,0 +1,158 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ This file is part of systemd.
+
+ Copyright 2012 Lennart Poettering
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <stdio.h>
+#include <getopt.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+
+#include "util.h"
+#include "def.h"
+#include "readahead-common.h"
+
+unsigned arg_files_max = 16*1024;
+off_t arg_file_size_max = READAHEAD_FILE_SIZE_MAX;
+usec_t arg_timeout = 2*USEC_PER_MINUTE;
+
+static int help(void) {
+
+ printf("%s [OPTIONS...] collect [DIRECTORY]\n\n"
+ "Collect read-ahead data on early boot.\n\n"
+ " -h --help Show this help\n"
+ " --max-files=INT Maximum number of files to read ahead\n"
+ " --file-size-max=BYTES Maximum size of files to read ahead\n"
+ " --timeout=USEC Maximum time to spend collecting data\n\n\n",
+ program_invocation_short_name);
+
+ printf("%s [OPTIONS...] replay [DIRECTORY]\n\n"
+ "Replay collected read-ahead data on early boot.\n\n"
+ " -h --help Show this help\n"
+ " --file-size-max=BYTES Maximum size of files to read ahead\n\n\n",
+ program_invocation_short_name);
+
+ printf("%s [OPTIONS...] analyze [PACK FILE]\n\n"
+ "Analyze collected read-ahead data.\n\n"
+ " -h --help Show this help\n",
+ program_invocation_short_name);
+
+ return 0;
+}
+
+static int parse_argv(int argc, char *argv[]) {
+
+ enum {
+ ARG_FILES_MAX = 0x100,
+ ARG_FILE_SIZE_MAX,
+ ARG_TIMEOUT
+ };
+
+ static const struct option options[] = {
+ { "help", no_argument, NULL, 'h' },
+ { "files-max", required_argument, NULL, ARG_FILES_MAX },
+ { "file-size-max", required_argument, NULL, ARG_FILE_SIZE_MAX },
+ { "timeout", required_argument, NULL, ARG_TIMEOUT },
+ { NULL, 0, NULL, 0 }
+ };
+
+ int c;
+
+ assert(argc >= 0);
+ assert(argv);
+
+ while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) {
+
+ switch (c) {
+
+ case 'h':
+ help();
+ return 0;
+
+ case ARG_FILES_MAX:
+ if (safe_atou(optarg, &arg_files_max) < 0 || arg_files_max <= 0) {
+ log_error("Failed to parse maximum number of files %s.", optarg);
+ return -EINVAL;
+ }
+ break;
+
+ case ARG_FILE_SIZE_MAX: {
+ unsigned long long ull;
+
+ if (safe_atollu(optarg, &ull) < 0 || ull <= 0) {
+ log_error("Failed to parse maximum file size %s.", optarg);
+ return -EINVAL;
+ }
+
+ arg_file_size_max = (off_t) ull;
+ break;
+ }
+
+ case ARG_TIMEOUT:
+ if (parse_usec(optarg, &arg_timeout) < 0 || arg_timeout <= 0) {
+ log_error("Failed to parse timeout %s.", optarg);
+ return -EINVAL;
+ }
+
+ break;
+
+ case '?':
+ return -EINVAL;
+
+ default:
+ log_error("Unknown option code %c", c);
+ return -EINVAL;
+ }
+ }
+
+ if (optind != argc-1 &&
+ optind != argc-2) {
+ help();
+ return -EINVAL;
+ }
+
+ return 1;
+}
+
+int main(int argc, char *argv[]) {
+ int r;
+
+ log_set_target(LOG_TARGET_SAFE);
+ log_parse_environment();
+ log_open();
+
+ umask(0022);
+
+ r = parse_argv(argc, argv);
+ if (r <= 0)
+ return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+
+ if (streq(argv[optind], "collect"))
+ return main_collect(argv[optind+1]);
+ else if (streq(argv[optind], "replay"))
+ return main_replay(argv[optind+1]);
+ else if (streq(argv[optind], "analyze"))
+ return main_analyze(argv[optind+1]);
+
+ log_error("Unknown verb %s.", argv[optind]);
+ return EXIT_FAILURE;
+}