Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 12bd22ba authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "init: Add readahead built-in command"

parents af6a2620 542aae44
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -447,6 +447,9 @@ Commands
`rmdir <path>`
> Calls rmdir(2) on the given path.

`readahead <file|dir>`
> Calls readahead(2) on the file or files within given directory.

`setprop <name> <value>`
> Set system property _name_ to _value_. Properties are expanded
  within _value_.
+63 −1
Original line number Diff line number Diff line
@@ -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}},