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

Commit cc857244 authored by David Anderson's avatar David Anderson Committed by Gerrit Code Review
Browse files

Merge "ueventd: the parallel restorecon dirs is configurable [1/1]"

parents 645a15db ddffa0ea
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -163,3 +163,13 @@ recommended that devices use genfscon for labeling sysfs nodes. However, some de
from enabling the parallelization option:

    parallel_restorecon enabled

Do parallel restorecon to speed up boot process, subdirectories under `/sys`
can be sliced by ueventd.rc, and run on multiple process.
    parallel_restorecon_dir <directory>

For example
    parallel_restorecon_dir /sys
    parallel_restorecon_dir /sys/devices
    parallel_restorecon_dir /sys/devices/platform
    parallel_restorecon_dir /sys/devices/platform/soc
+40 −10
Original line number Diff line number Diff line
@@ -115,11 +115,13 @@ class ColdBoot {
  public:
    ColdBoot(UeventListener& uevent_listener,
             std::vector<std::unique_ptr<UeventHandler>>& uevent_handlers,
             bool enable_parallel_restorecon)
             bool enable_parallel_restorecon,
             std::vector<std::string> parallel_restorecon_queue)
        : uevent_listener_(uevent_listener),
          uevent_handlers_(uevent_handlers),
          num_handler_subprocesses_(std::thread::hardware_concurrency() ?: 4),
          enable_parallel_restorecon_(enable_parallel_restorecon) {}
          enable_parallel_restorecon_(enable_parallel_restorecon),
          parallel_restorecon_queue_(parallel_restorecon_queue) {}

    void Run();

@@ -142,6 +144,8 @@ class ColdBoot {
    std::set<pid_t> subprocess_pids_;

    std::vector<std::string> restorecon_queue_;

    std::vector<std::string> parallel_restorecon_queue_;
};

void ColdBoot::UeventHandlerMain(unsigned int process_num, unsigned int total_processes) {
@@ -155,17 +159,34 @@ void ColdBoot::UeventHandlerMain(unsigned int process_num, unsigned int total_pr
}

void ColdBoot::RestoreConHandler(unsigned int process_num, unsigned int total_processes) {
    android::base::Timer t_process;

    for (unsigned int i = process_num; i < restorecon_queue_.size(); i += total_processes) {
        android::base::Timer t;
        auto& dir = restorecon_queue_[i];

        selinux_android_restorecon(dir.c_str(), SELINUX_ANDROID_RESTORECON_RECURSE);

        //Mark a dir restorecon operation for 50ms,
        //Maybe you can add this dir to the ueventd.rc script to parallel processing
        if (t.duration() > 50ms) {
            LOG(INFO) << "took " << t.duration().count() <<"ms restorecon '"
                        << dir.c_str() << "' on process '" << process_num  <<"'";
        }
    }

    //Calculate process restorecon time
    LOG(VERBOSE) << "took " << t_process.duration().count() << "ms on process '"
                << process_num  << "'";
}

void ColdBoot::GenerateRestoreCon(const std::string& directory) {
    std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(directory.c_str()), &closedir);

    if (!dir) return;
    if (!dir) {
        PLOG(WARNING) << "opendir " << directory.c_str();
        return;
    }

    struct dirent* dent;
    while ((dent = readdir(dir.get())) != NULL) {
@@ -176,7 +197,10 @@ void ColdBoot::GenerateRestoreCon(const std::string& directory) {

        if (S_ISDIR(st.st_mode)) {
            std::string fullpath = directory + "/" + dent->d_name;
            if (fullpath != "/sys/devices") {
            auto parallel_restorecon =
                std::find(parallel_restorecon_queue_.begin(),
                    parallel_restorecon_queue_.end(), fullpath);
            if (parallel_restorecon == parallel_restorecon_queue_.end()) {
                restorecon_queue_.emplace_back(fullpath);
            }
        }
@@ -248,11 +272,16 @@ void ColdBoot::Run() {
    RegenerateUevents();

    if (enable_parallel_restorecon_) {
        selinux_android_restorecon("/sys", 0);
        selinux_android_restorecon("/sys/devices", 0);
        GenerateRestoreCon("/sys");
        if (parallel_restorecon_queue_.empty()) {
            parallel_restorecon_queue_.emplace_back("/sys");
            // takes long time for /sys/devices, parallelize it
        GenerateRestoreCon("/sys/devices");
            parallel_restorecon_queue_.emplace_back("/sys/devices");
            LOG(INFO) << "Parallel processing directory is not set, set the default";
        }
        for (const auto& dir : parallel_restorecon_queue_) {
            selinux_android_restorecon(dir.c_str(), 0);
            GenerateRestoreCon(dir);
        }
    }

    ForkSubProcesses();
@@ -326,7 +355,8 @@ int ueventd_main(int argc, char** argv) {

    if (!android::base::GetBoolProperty(kColdBootDoneProp, false)) {
        ColdBoot cold_boot(uevent_listener, uevent_handlers,
                           ueventd_configuration.enable_parallel_restorecon);
                           ueventd_configuration.enable_parallel_restorecon,
                           ueventd_configuration.parallel_restorecon_dirs);
        cold_boot.Run();
    }

+14 −0
Original line number Diff line number Diff line
@@ -151,6 +151,17 @@ Result<void> ParseEnabledDisabledLine(std::vector<std::string>&& args, bool* fea
    return {};
}

Result<void> ParseParallelRestoreconDirsLine(std::vector<std::string>&& args,
                                          std::vector<std::string>* parallel_restorecon_dirs) {
    if (args.size() != 2) {
        return Error() << "parallel_restorecon_dir lines must have exactly 2 parameters";
    }

    std::move(std::next(args.begin()), args.end(), std::back_inserter(*parallel_restorecon_dirs));

    return {};
}

Result<void> ParseUeventSocketRcvbufSizeLine(std::vector<std::string>&& args,
                                             size_t* uevent_socket_rcvbuf_size) {
    if (args.size() != 2) {
@@ -268,6 +279,9 @@ UeventdConfiguration ParseConfig(const std::vector<std::string>& configs) {
    parser.AddSingleLineParser("uevent_socket_rcvbuf_size",
                               std::bind(ParseUeventSocketRcvbufSizeLine, _1,
                                         &ueventd_configuration.uevent_socket_rcvbuf_size));
    parser.AddSingleLineParser("parallel_restorecon_dir",
                               std::bind(ParseParallelRestoreconDirsLine, _1,
                                         &ueventd_configuration.parallel_restorecon_dirs));
    parser.AddSingleLineParser("parallel_restorecon",
                               std::bind(ParseEnabledDisabledLine, _1,
                                         &ueventd_configuration.enable_parallel_restorecon));
+1 −0
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ struct UeventdConfiguration {
    std::vector<Permissions> dev_permissions;
    std::vector<std::string> firmware_directories;
    std::vector<ExternalFirmwareHandler> external_firmware_handlers;
    std::vector<std::string> parallel_restorecon_dirs;
    bool enable_modalias_handling = false;
    size_t uevent_socket_rcvbuf_size = 0;
    bool enable_parallel_restorecon = false;
+36 −9
Original line number Diff line number Diff line
@@ -77,6 +77,7 @@ void TestUeventdFile(const std::string& content, const UeventdConfiguration& exp
    EXPECT_EQ(expected.firmware_directories, result.firmware_directories);
    TestVector(expected.external_firmware_handlers, result.external_firmware_handlers,
               TestExternalFirmwareHandler);
    EXPECT_EQ(expected.parallel_restorecon_dirs, result.parallel_restorecon_dirs);
}

TEST(ueventd_parser, EmptyFile) {
@@ -105,7 +106,7 @@ subsystem test_devpath_dirname
            {"test_devname2", Subsystem::DEVNAME_UEVENT_DEVNAME, "/dev"},
            {"test_devpath_dirname", Subsystem::DEVNAME_UEVENT_DEVPATH, "/dev/graphics"}};

    TestUeventdFile(ueventd_file, {subsystems, {}, {}, {}, {}});
    TestUeventdFile(ueventd_file, {subsystems, {}, {}, {}, {}, {}});
}

TEST(ueventd_parser, Permissions) {
@@ -131,7 +132,7 @@ TEST(ueventd_parser, Permissions) {
            {"/sys/devices/virtual/*/input", "poll_delay", 0660, AID_ROOT, AID_INPUT, true},
    };

    TestUeventdFile(ueventd_file, {{}, sysfs_permissions, permissions, {}, {}});
    TestUeventdFile(ueventd_file, {{}, sysfs_permissions, permissions, {}, {}, {}});
}

TEST(ueventd_parser, FirmwareDirectories) {
@@ -147,7 +148,7 @@ firmware_directories /more
            "/more",
    };

    TestUeventdFile(ueventd_file, {{}, {}, {}, firmware_directories, {}});
    TestUeventdFile(ueventd_file, {{}, {}, {}, firmware_directories, {}, {}});
}

TEST(ueventd_parser, ExternalFirmwareHandlers) {
@@ -213,7 +214,7 @@ external_firmware_handler /devices/path/firmware/something004.bin radio radio "/
            },
    };

    TestUeventdFile(ueventd_file, {{}, {}, {}, {}, external_firmware_handlers});
    TestUeventdFile(ueventd_file, {{}, {}, {}, {}, external_firmware_handlers, {}});
}

TEST(ueventd_parser, ExternalFirmwareHandlersDuplicate) {
@@ -231,7 +232,21 @@ external_firmware_handler devpath root handler_path2
            },
    };

    TestUeventdFile(ueventd_file, {{}, {}, {}, {}, external_firmware_handlers});
    TestUeventdFile(ueventd_file, {{}, {}, {}, {}, external_firmware_handlers, {}});
}

TEST(ueventd_parser, ParallelRestoreconDirs) {
    auto ueventd_file = R"(
parallel_restorecon_dir /sys
parallel_restorecon_dir /sys/devices
)";

    auto parallel_restorecon_dirs = std::vector<std::string>{
            "/sys",
            "/sys/devices",
    };

    TestUeventdFile(ueventd_file, {{}, {}, {}, {}, {}, parallel_restorecon_dirs});
}

TEST(ueventd_parser, UeventSocketRcvbufSize) {
@@ -240,7 +255,7 @@ uevent_socket_rcvbuf_size 8k
uevent_socket_rcvbuf_size 8M
)";

    TestUeventdFile(ueventd_file, {{}, {}, {}, {}, {}, false, 8 * 1024 * 1024});
    TestUeventdFile(ueventd_file, {{}, {}, {}, {}, {}, {}, false, 8 * 1024 * 1024});
}

TEST(ueventd_parser, EnabledDisabledLines) {
@@ -250,7 +265,7 @@ parallel_restorecon enabled
modalias_handling disabled
)";

    TestUeventdFile(ueventd_file, {{}, {}, {}, {}, {}, false, 0, true});
    TestUeventdFile(ueventd_file, {{}, {}, {}, {}, {}, {}, false, 0, true});

    auto ueventd_file2 = R"(
parallel_restorecon enabled
@@ -258,7 +273,7 @@ modalias_handling enabled
parallel_restorecon disabled
)";

    TestUeventdFile(ueventd_file2, {{}, {}, {}, {}, {}, true, 0, false});
    TestUeventdFile(ueventd_file2, {{}, {}, {}, {}, {}, {}, true, 0, false});
}

TEST(ueventd_parser, AllTogether) {
@@ -298,6 +313,9 @@ uevent_socket_rcvbuf_size 6M
modalias_handling enabled
parallel_restorecon enabled

parallel_restorecon_dir /sys
parallel_restorecon_dir /sys/devices

#ending comment
)";

@@ -330,11 +348,17 @@ parallel_restorecon enabled
            {"/devices/path/firmware/firmware001.bin", AID_ROOT, AID_ROOT, "/vendor/bin/touch.sh"},
    };

    auto parallel_restorecon_dirs = std::vector<std::string>{
            "/sys",
            "/sys/devices",
    };

    size_t uevent_socket_rcvbuf_size = 6 * 1024 * 1024;

    TestUeventdFile(ueventd_file,
                    {subsystems, sysfs_permissions, permissions, firmware_directories,
                     external_firmware_handlers, true, uevent_socket_rcvbuf_size, true});
                     external_firmware_handlers, parallel_restorecon_dirs, true,
                     uevent_socket_rcvbuf_size, true});
}

// All of these lines are ill-formed, so test that there is 0 output.
@@ -366,6 +390,9 @@ external_firmware_handler
external_firmware_handler blah blah
external_firmware_handler blah blah blah blah

parallel_restorecon_dir
parallel_restorecon_dir /sys /sys/devices

)";

    TestUeventdFile(ueventd_file, {});