diff options
author | Wei Wang <wvw@google.com> | 2017-08-11 22:15:29 +0000 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2017-08-11 22:15:29 +0000 |
commit | 67eac4fa36c4c26cefbfcd8b56c32dc7ad585512 (patch) | |
tree | a73902a98fcc124479c81cf232e4a4d8284f1738 /init/builtins.cpp | |
parent | f49aa1323fdc036cdc0f347d66b2a0629b1a3f14 (diff) | |
parent | 826bc7b5072ecc8283721a82ac2b16bd9127e57b (diff) |
Merge "init: Add readahead built-in command" am: 12bd22badf
am: 826bc7b507
Change-Id: I3cdb1022bf863c5ffd58be0d7af5f6712c818365
Diffstat (limited to 'init/builtins.cpp')
-rw-r--r-- | init/builtins.cpp | 64 |
1 files changed, 63 insertions, 1 deletions
diff --git a/init/builtins.cpp b/init/builtins.cpp index 5335608bc..eea78fd1c 100644 --- a/init/builtins.cpp +++ b/init/builtins.cpp @@ -19,6 +19,7 @@ #include <dirent.h> #include <errno.h> #include <fcntl.h> +#include <fts.h> #include <linux/loop.h> #include <linux/module.h> #include <mntent.h> @@ -627,7 +628,7 @@ static int do_rmdir(const std::vector<std::string>& args) { static int do_sysclktz(const std::vector<std::string>& args) { struct timezone tz = {}; - if (android::base::ParseInt(args[1], &tz.tz_minuteswest) && settimeofday(NULL, &tz) != -1) { + if (android::base::ParseInt(args[1], &tz.tz_minuteswest) && settimeofday(nullptr, &tz) != -1) { return 0; } return -1; @@ -660,6 +661,66 @@ static int do_write(const std::vector<std::string>& args) { return 0; } +static int do_readahead(const std::vector<std::string>& args) { + struct stat sb; + + if (stat(args[1].c_str(), &sb)) { + PLOG(ERROR) << "Error opening " << args[1]; + return -1; + } + + // We will do readahead in a forked process in order not to block init + // since it may block while it reads the + // filesystem metadata needed to locate the requested blocks. This + // occurs frequently with ext[234] on large files using indirect blocks + // instead of extents, giving the appearance that the call blocks until + // the requested data has been read. + pid_t pid = fork(); + if (pid == 0) { + android::base::Timer t; + if (S_ISREG(sb.st_mode)) { + android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(args[1].c_str(), O_RDONLY))); + if (fd == -1) { + PLOG(ERROR) << "Error opening file: " << args[1]; + _exit(EXIT_FAILURE); + } + if (readahead(fd, 0, std::numeric_limits<size_t>::max())) { + PLOG(ERROR) << "Error readahead file: " << args[1]; + _exit(EXIT_FAILURE); + } + } else if (S_ISDIR(sb.st_mode)) { + char* paths[] = {const_cast<char*>(args[1].data()), nullptr}; + std::unique_ptr<FTS, decltype(&fts_close)> fts( + fts_open(paths, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, nullptr), fts_close); + if (!fts) { + PLOG(ERROR) << "Error opening directory: " << args[1]; + _exit(EXIT_FAILURE); + } + // Traverse the entire hierarchy and do readahead + for (FTSENT* ftsent = fts_read(fts.get()); ftsent != nullptr; + ftsent = fts_read(fts.get())) { + if (ftsent->fts_info & FTS_F) { + android::base::unique_fd fd( + TEMP_FAILURE_RETRY(open(ftsent->fts_accpath, O_RDONLY))); + if (fd == -1) { + PLOG(ERROR) << "Error opening file: " << args[1]; + continue; + } + if (readahead(fd, 0, std::numeric_limits<size_t>::max())) { + PLOG(ERROR) << "Unable to readahead on file: " << ftsent->fts_accpath; + } + } + } + } + LOG(INFO) << "Readahead " << args[1] << " took " << t; + _exit(0); + } else if (pid < 0) { + PLOG(ERROR) << "Fork failed"; + return -1; + } + return 0; +} + static int do_copy(const std::vector<std::string>& args) { std::string data; std::string err; @@ -898,6 +959,7 @@ const BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const { {"mount_all", {1, kMax, do_mount_all}}, {"mount", {3, kMax, do_mount}}, {"umount", {1, 1, do_umount}}, + {"readahead", {1, 1, do_readahead}}, {"restart", {1, 1, do_restart}}, {"restorecon", {1, kMax, do_restorecon}}, {"restorecon_recursive", {1, kMax, do_restorecon_recursive}}, |