summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore4
-rw-r--r--Makefile.am25
-rw-r--r--TODO2
-rw-r--r--src/readahead/readahead-analyze.c25
-rw-r--r--src/readahead/readahead-collect.c118
-rw-r--r--src/readahead/readahead-common.h9
-rw-r--r--src/readahead/readahead-replay.c94
-rw-r--r--src/readahead/readahead.c158
-rw-r--r--units/systemd-readahead-collect.service.in2
-rw-r--r--units/systemd-readahead-replay.service.in2
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 \
diff --git a/TODO b/TODO
index 630721c3f2..908dadb974 100644
--- a/TODO
+++ b/TODO
@@ -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