X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Freadahead%2Freadahead-collect.c;h=a88e7f2d70f2e1a1d2733bf8e53872ad6b2b8b61;hb=4019a16d5b65633e5f6d671c16d3215d7f7f29fc;hp=7e6c243b5e1be0ddb5321df5a9558cc19c7bec4b;hpb=19c5f19d69bb5f520fa7213239490c55de06d99d;p=elogind.git diff --git a/src/readahead/readahead-collect.c b/src/readahead/readahead-collect.c index 7e6c243b5..a88e7f2d7 100644 --- a/src/readahead/readahead-collect.c +++ b/src/readahead/readahead-collect.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + 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 - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ @@ -233,10 +233,25 @@ static int collect(const char *root) { bool on_ssd, on_btrfs; struct statfs sfs; usec_t not_after; + uint64_t previous_block_readahead; + bool previous_block_readahead_set = false; assert(root); - write_one_line_file("/proc/self/oom_score_adj", "1000"); + if (asprintf(&pack_fn, "%s/.readahead", root) < 0) { + log_error("Out of memory"); + r = -ENOMEM; + goto finish; + } + + /* If there's no pack file yet we lower the kernel readahead + * so that mincore() is accurate. If there is a pack file + * already we assume it is accurate enough so that kernel + * readahead is never triggered. */ + previous_block_readahead_set = + access(pack_fn, F_OK) < 0 && + block_get_readahead(root, &previous_block_readahead) >= 0 && + block_set_readahead(root, 8*1024) >= 0; if (ioprio_set(IOPRIO_WHO_PROCESS, getpid(), IOPRIO_PRIO_VALUE(IOPRIO_CLASS_IDLE, 0)) < 0) log_warning("Failed to set IDLE IO priority class: %m"); @@ -458,10 +473,7 @@ done: on_btrfs = statfs(root, &sfs) >= 0 && (long) sfs.f_type == (long) BTRFS_SUPER_MAGIC; log_debug("On btrfs: %s", yes_no(on_btrfs)); - asprintf(&pack_fn, "%s/.readahead", root); - asprintf(&pack_fn_new, "%s/.readahead.new", root); - - if (!pack_fn || !pack_fn_new) { + if (asprintf(&pack_fn_new, "%s/.readahead.new", root) < 0) { log_error("Out of memory"); r = -ENOMEM; goto finish; @@ -551,7 +563,6 @@ finish: fclose(pack); unlink(pack_fn_new); } - free(pack_fn_new); free(pack_fn); @@ -560,6 +571,16 @@ finish: hashmap_free(files); + if (previous_block_readahead_set) { + uint64_t bytes; + + /* Restore the original kernel readahead setting if we + * changed it, and nobody has overwritten it since + * yet. */ + if (block_get_readahead(root, &bytes) >= 0 && bytes == 8*1024) + block_set_readahead(root, previous_block_readahead); + } + return r; } @@ -660,11 +681,17 @@ int main(int argc, char *argv[]) { umask(0022); - if ((r = parse_argv(argc, argv)) <= 0) + r = parse_argv(argc, argv); + if (r <= 0) return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; root = optind < argc ? argv[optind] : "/"; + /* Skip this step on read-only media. Note that we check the + * underlying block device here, not he read-only flag of the + * file system on top, since that one is most likely mounted + * read-only anyway at boot, even if the underlying block + * device is theoretically writable. */ if (fs_on_read_only(root) > 0) { log_info("Disabling readahead collector due to read-only media."); return 0; @@ -675,12 +702,8 @@ int main(int argc, char *argv[]) { return 0; } - if (detect_virtualization(NULL) > 0) { - log_info("Disabling readahead collector due to execution in virtualized environment."); - return 0; - } - - if (!(shared = shared_get())) + shared = shared_get(); + if (!shared) return 1; shared->collect = getpid();