diff options
-rw-r--r-- | .gitignore | 4 | ||||
-rw-r--r-- | Makefile.am | 25 | ||||
-rw-r--r-- | TODO | 2 | ||||
-rw-r--r-- | src/readahead/readahead-analyze.c | 25 | ||||
-rw-r--r-- | src/readahead/readahead-collect.c | 118 | ||||
-rw-r--r-- | src/readahead/readahead-common.h | 9 | ||||
-rw-r--r-- | src/readahead/readahead-replay.c | 94 | ||||
-rw-r--r-- | src/readahead/readahead.c | 158 | ||||
-rw-r--r-- | units/systemd-readahead-collect.service.in | 2 | ||||
-rw-r--r-- | units/systemd-readahead-replay.service.in | 2 |
10 files changed, 201 insertions, 238 deletions
diff --git a/.gitignore b/.gitignore index abb7255c49..7d04930a25 100644 --- a/.gitignore +++ b/.gitignore @@ -46,8 +46,7 @@ /systemd-user-sessions /systemd-shutdown /systemd-tmpfiles -/systemd-readahead-collect -/systemd-readahead-replay +/systemd-readahead /systemd-reply-password /systemd-gnome-ask-password-agent /systemd-ask-password @@ -123,4 +122,3 @@ stamp-* /v4l_id /test-libudev /test-udev -/systemd-readahead-analyze diff --git a/Makefile.am b/Makefile.am index 4616b30f7b..03e28e8c34 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2377,39 +2377,24 @@ endif # ------------------------------------------------------------------------------ if ENABLE_READAHEAD -systemd_readahead_collect_SOURCES = \ +systemd_readahead_SOURCES = \ + src/readahead/readahead.c \ src/readahead/readahead-collect.c \ - src/readahead/readahead-common.c \ - src/readahead/readahead-common.h - -systemd_readahead_collect_LDADD = \ - libsystemd-shared.la \ - libsystemd-daemon.la \ - libudev.la - -systemd_readahead_replay_SOURCES = \ src/readahead/readahead-replay.c \ + src/readahead/readahead-analyze.c \ src/readahead/readahead-common.c \ src/readahead/readahead-common.h -systemd_readahead_replay_LDADD = \ +systemd_readahead_LDADD = \ libsystemd-shared.la \ libsystemd-daemon.la \ libudev.la -systemd_readahead_analyze_SOURCES = \ - src/readahead/readahead-analyze.c \ - src/readahead/readahead-common.h - pkginclude_HEADERS += \ src/systemd/sd-readahead.h rootlibexec_PROGRAMS += \ - systemd-readahead-collect \ - systemd-readahead-replay - -bin_PROGRAMS += \ - systemd-readahead-analyze + systemd-readahead dist_systemunit_DATA += \ units/systemd-readahead-drop.service \ @@ -35,8 +35,6 @@ Features: * supprto rd.xxx wherever else makes sense -* readahead: merge the three tools into one binary - * systemctl: when stopping a service which has triggres and warning about it actually check the TriggeredBy= deps fields * journal: hook up with EFI firmware log, new kmsg logic diff --git a/src/readahead/readahead-analyze.c b/src/readahead/readahead-analyze.c index 6ee355146a..5a5b9176d0 100644 --- a/src/readahead/readahead-analyze.c +++ b/src/readahead/readahead-analyze.c @@ -32,8 +32,7 @@ #include "readahead-common.h" - -int main(int argc, char *argv[]) +int main_analyze(const char *pack_path) { char line[1024]; char path[PATH_MAX]; @@ -48,30 +47,28 @@ int main(int argc, char *argv[]) struct stat st; int pagesize = getpagesize(); - if (argc != 2) - snprintf(path, PATH_MAX, "/.readahead"); - else - snprintf(path, PATH_MAX, "%s", argv[1]); + if (!pack_path) + pack_path = "/.readahead"; - pack = fopen(path, "r"); + pack = fopen(pack_path, "r"); if (!pack) { fprintf(stderr, "Pack file missing\n"); - exit(EXIT_FAILURE); + return EXIT_FAILURE; } if (!(fgets(line, sizeof(line), pack))) { fprintf(stderr, "Pack file corrupt\n"); - exit(EXIT_FAILURE); + return EXIT_FAILURE; } if (!strstr(line, READAHEAD_PACK_FILE_VERSION)) { fprintf(stderr, "Pack file version incompatible with this parser\n"); - exit(EXIT_FAILURE); + return EXIT_FAILURE; } if ((a = getc(pack)) == EOF) { fprintf(stderr, "Pack file corrupt\n"); - exit(EXIT_FAILURE); + return EXIT_FAILURE; } fprintf(stdout, " pct sections size: path\n"); @@ -88,14 +85,14 @@ int main(int argc, char *argv[]) if (fread(&inode, sizeof(inode), 1, pack) != 1) { fprintf(stderr, "Pack file corrupt\n"); - exit(EXIT_FAILURE); + return EXIT_FAILURE; } while (true) { if (fread(&b, sizeof(b), 1, pack) != 1 || fread(&c, sizeof(c), 1, pack) != 1) { fprintf(stderr, "Pack file corrupt\n"); - exit(EXIT_FAILURE); + return EXIT_FAILURE; } if ((b == 0) && (c == 0)) break; @@ -137,5 +134,5 @@ int main(int argc, char *argv[]) fprintf(stdout, "MISSING: %d\n", missing); fprintf(stdout, "TOTAL: %ld\n", tsize); - exit(EXIT_SUCCESS); + return EXIT_SUCCESS; } diff --git a/src/readahead/readahead-collect.c b/src/readahead/readahead-collect.c index c4bcd4e162..8dacf6af5c 100644 --- a/src/readahead/readahead-collect.c +++ b/src/readahead/readahead-collect.c @@ -62,10 +62,6 @@ * - does ioprio_set work with fadvise()? */ -static unsigned arg_files_max = 16*1024; -static off_t arg_file_size_max = READAHEAD_FILE_SIZE_MAX; -static usec_t arg_timeout = 2*USEC_PER_MINUTE; - static ReadaheadShared *shared = NULL; /* Avoid collisions with the NULL pointer */ @@ -592,108 +588,10 @@ finish: return r; } -static int help(void) { - - printf("%s [OPTIONS...] [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" - " --max-file-size=BYTES Maximum size of files to read ahead\n" - " --timeout=USEC Maximum time to spend collecting data\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); +int main_collect(const char *root) { - 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 && - optind != argc-1) { - help(); - return -EINVAL; - } - - return 1; -} - -int main(int argc, char *argv[]) { - int r; - const char *root; - - 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; - - root = optind < argc ? argv[optind] : "/"; + if (!root) + root = "/"; /* Skip this step on read-only media. Note that we check the * underlying block device here, not he read-only flag of the @@ -702,23 +600,23 @@ int main(int argc, char *argv[]) { * device is theoretically writable. */ if (fs_on_read_only(root) > 0) { log_info("Disabling readahead collector due to read-only media."); - return 0; + return EXIT_SUCCESS; } if (!enough_ram()) { log_info("Disabling readahead collector due to low memory."); - return 0; + return EXIT_SUCCESS; } shared = shared_get(); if (!shared) - return 1; + return EXIT_FAILURE; shared->collect = getpid(); __sync_synchronize(); if (collect(root) < 0) - return 1; + return EXIT_FAILURE; - return 0; + return EXIT_SUCCESS; } diff --git a/src/readahead/readahead-common.h b/src/readahead/readahead-common.h index 3056a02485..fd657a2d4d 100644 --- a/src/readahead/readahead-common.h +++ b/src/readahead/readahead-common.h @@ -26,11 +26,16 @@ #include <sys/types.h> #include "macro.h" +#include "util.h" #define READAHEAD_FILE_SIZE_MAX (10*1024*1024) #define READAHEAD_PACK_FILE_VERSION ";VERSION=2\n" +extern unsigned arg_files_max; +extern off_t arg_file_size_max; +extern usec_t arg_timeout; + int file_verify(int fd, const char *fn, off_t file_size_max, struct stat *st); int fs_on_ssd(const char *p); @@ -52,4 +57,8 @@ int block_bump_request_nr(const char *p); int block_get_readahead(const char *p, uint64_t *bytes); int block_set_readahead(const char *p, uint64_t bytes); +int main_collect(const char *root); +int main_replay(const char *root); +int main_analyze(const char *pack_path); + #endif diff --git a/src/readahead/readahead-replay.c b/src/readahead/readahead-replay.c index fc2c33fcc1..6e6db601d4 100644 --- a/src/readahead/readahead-replay.c +++ b/src/readahead/readahead-replay.c @@ -44,8 +44,6 @@ #include "readahead-common.h" #include "virt.h" -static off_t arg_file_size_max = READAHEAD_FILE_SIZE_MAX; - static ReadaheadShared *shared = NULL; static int unpack_file(FILE *pack) { @@ -289,103 +287,25 @@ finish: return r; } +int main_replay(const char *root) { -static int help(void) { - - printf("%s [OPTIONS...] [DIRECTORY]\n\n" - "Replay collected read-ahead data on early boot.\n\n" - " -h --help Show this help\n" - " --max-file-size=BYTES Maximum size of files to read ahead\n", - program_invocation_short_name); - - return 0; -} - -static int parse_argv(int argc, char *argv[]) { - - enum { - ARG_FILE_SIZE_MAX - }; - - static const struct option options[] = { - { "help", no_argument, NULL, 'h' }, - { "file-size-max", required_argument, NULL, ARG_FILE_SIZE_MAX }, - { 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_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 '?': - return -EINVAL; - - default: - log_error("Unknown option code %c", c); - return -EINVAL; - } - } - - if (optind != argc && - optind != argc-1) { - help(); - return -EINVAL; - } - - return 1; -} - -int main(int argc, char*argv[]) { - int r; - const char *root; - - 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; - - root = optind < argc ? argv[optind] : "/"; + if (!root) + root = "/"; if (!enough_ram()) { log_info("Disabling readahead replay due to low memory."); - return 0; + return EXIT_SUCCESS; } shared = shared_get(); if (!shared) - return 1; + return EXIT_FAILURE; shared->replay = getpid(); __sync_synchronize(); if (replay(root) < 0) - return 1; + return EXIT_FAILURE; - return 0; + return EXIT_SUCCESS; } diff --git a/src/readahead/readahead.c b/src/readahead/readahead.c new file mode 100644 index 0000000000..abeecc7634 --- /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; +} diff --git a/units/systemd-readahead-collect.service.in b/units/systemd-readahead-collect.service.in index 55b6776649..c597cdc5aa 100644 --- a/units/systemd-readahead-collect.service.in +++ b/units/systemd-readahead-collect.service.in @@ -17,7 +17,7 @@ ConditionVirtualization=no [Service] Type=notify -ExecStart=@rootlibexecdir@/systemd-readahead-collect +ExecStart=@rootlibexecdir@/systemd-readahead collect RemainAfterExit=yes StandardOutput=null OOMScoreAdjust=1000 diff --git a/units/systemd-readahead-replay.service.in b/units/systemd-readahead-replay.service.in index 7324ba36c5..eddf36df95 100644 --- a/units/systemd-readahead-replay.service.in +++ b/units/systemd-readahead-replay.service.in @@ -16,7 +16,7 @@ ConditionVirtualization=no [Service] Type=notify -ExecStart=@rootlibexecdir@/systemd-readahead-replay +ExecStart=@rootlibexecdir@/systemd-readahead replay RemainAfterExit=yes StandardOutput=null OOMScoreAdjust=1000 |