ueventd: parallelize restorecon /sys

generate subdir for /sys and /sys/devices, handle restorecon in parallel.

This reduces coldboot time on our target about 300ms.

Change-Id: I9c3d0e97aacff0ca127880d936dfd5fcc2aee125
This commit is contained in:
Bongkyu Kim 2019-01-30 19:59:53 +09:00
parent 536dd4292e
commit 5aa6197d5f
1 changed files with 43 additions and 7 deletions

View File

@ -17,12 +17,15 @@
#include "ueventd.h"
#include <ctype.h>
#include <dirent.h>
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
#include <set>
#include <thread>
@ -121,8 +124,9 @@ class ColdBoot {
void UeventHandlerMain(unsigned int process_num, unsigned int total_processes);
void RegenerateUevents();
void ForkSubProcesses();
void DoRestoreCon();
void WaitForSubProcesses();
void RestoreConHandler(unsigned int process_num, unsigned int total_processes);
void GenerateRestoreCon(const std::string& directory);
UeventListener& uevent_listener_;
std::vector<std::unique_ptr<UeventHandler>>& uevent_handlers_;
@ -131,6 +135,8 @@ class ColdBoot {
std::vector<Uevent> uevent_queue_;
std::set<pid_t> subprocess_pids_;
std::vector<std::string> restorecon_queue_;
};
void ColdBoot::UeventHandlerMain(unsigned int process_num, unsigned int total_processes) {
@ -141,9 +147,38 @@ void ColdBoot::UeventHandlerMain(unsigned int process_num, unsigned int total_pr
uevent_handler->HandleUevent(uevent);
}
}
}
void ColdBoot::RestoreConHandler(unsigned int process_num, unsigned int total_processes) {
for (unsigned int i = process_num; i < restorecon_queue_.size(); i += total_processes) {
auto& dir = restorecon_queue_[i];
selinux_android_restorecon(dir.c_str(), SELINUX_ANDROID_RESTORECON_RECURSE);
}
_exit(EXIT_SUCCESS);
}
void ColdBoot::GenerateRestoreCon(const std::string& directory) {
std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(directory.c_str()), &closedir);
if (!dir) return;
struct dirent* dent;
while ((dent = readdir(dir.get())) != NULL) {
if (strcmp(dent->d_name, ".") == 0 || strcmp(dent->d_name, "..") == 0) continue;
struct stat st;
if (fstatat(dirfd(dir.get()), dent->d_name, &st, 0) == -1) continue;
if (S_ISDIR(st.st_mode)) {
std::string fullpath = directory + "/" + dent->d_name;
if (fullpath != "/sys/devices") {
restorecon_queue_.emplace_back(fullpath);
}
}
}
}
void ColdBoot::RegenerateUevents() {
uevent_listener_.RegenerateUevents([this](const Uevent& uevent) {
uevent_queue_.emplace_back(uevent);
@ -160,16 +195,13 @@ void ColdBoot::ForkSubProcesses() {
if (pid == 0) {
UeventHandlerMain(i, num_handler_subprocesses_);
RestoreConHandler(i, num_handler_subprocesses_);
}
subprocess_pids_.emplace(pid);
}
}
void ColdBoot::DoRestoreCon() {
selinux_android_restorecon("/sys", SELINUX_ANDROID_RESTORECON_RECURSE);
}
void ColdBoot::WaitForSubProcesses() {
// Treat subprocesses that crash or get stuck the same as if ueventd itself has crashed or gets
// stuck.
@ -208,9 +240,13 @@ void ColdBoot::Run() {
RegenerateUevents();
ForkSubProcesses();
selinux_android_restorecon("/sys", 0);
selinux_android_restorecon("/sys/devices", 0);
GenerateRestoreCon("/sys");
// takes long time for /sys/devices, parallelize it
GenerateRestoreCon("/sys/devices");
DoRestoreCon();
ForkSubProcesses();
WaitForSubProcesses();