Merge "Add memcg related configs to init."
This commit is contained in:
commit
b84666cbc0
5 changed files with 111 additions and 13 deletions
|
|
@ -260,6 +260,18 @@ runs the service.
|
||||||
> Sets the child's /proc/self/oom\_score\_adj to the specified value,
|
> Sets the child's /proc/self/oom\_score\_adj to the specified value,
|
||||||
which must range from -1000 to 1000.
|
which must range from -1000 to 1000.
|
||||||
|
|
||||||
|
`memcg.swappiness <value>`
|
||||||
|
> Sets the child's memory.swappiness to the specified value (only if memcg is mounted),
|
||||||
|
which must be equal or greater than 0.
|
||||||
|
|
||||||
|
`memcg.soft_limit_in_bytes <value>`
|
||||||
|
> Sets the child's memory.soft_limit_in_bytes to the specified value (only if memcg is mounted),
|
||||||
|
which must be equal or greater than 0.
|
||||||
|
|
||||||
|
`memcg.limit_in_bytes <value>`
|
||||||
|
> Sets the child's memory.limit_in_bytes to the specified value (only if memcg is mounted),
|
||||||
|
which must be equal or greater than 0.
|
||||||
|
|
||||||
`shutdown <shutdown_behavior>`
|
`shutdown <shutdown_behavior>`
|
||||||
> Set shutdown behavior of the service process. When this is not specified,
|
> Set shutdown behavior of the service process. When this is not specified,
|
||||||
the service is killed during shutdown process by using SIGTERM and SIGKILL.
|
the service is killed during shutdown process by using SIGTERM and SIGKILL.
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,9 @@ Service::Service(const std::string& name, const std::vector<std::string>& args)
|
||||||
ioprio_pri_(0),
|
ioprio_pri_(0),
|
||||||
priority_(0),
|
priority_(0),
|
||||||
oom_score_adjust_(-1000),
|
oom_score_adjust_(-1000),
|
||||||
|
swappiness_(-1),
|
||||||
|
soft_limit_in_bytes_(-1),
|
||||||
|
limit_in_bytes_(-1),
|
||||||
args_(args) {
|
args_(args) {
|
||||||
onrestart_.InitSingleTrigger("onrestart");
|
onrestart_.InitSingleTrigger("onrestart");
|
||||||
}
|
}
|
||||||
|
|
@ -196,6 +199,9 @@ Service::Service(const std::string& name, unsigned flags, uid_t uid, gid_t gid,
|
||||||
ioprio_pri_(0),
|
ioprio_pri_(0),
|
||||||
priority_(0),
|
priority_(0),
|
||||||
oom_score_adjust_(-1000),
|
oom_score_adjust_(-1000),
|
||||||
|
swappiness_(-1),
|
||||||
|
soft_limit_in_bytes_(-1),
|
||||||
|
limit_in_bytes_(-1),
|
||||||
args_(args) {
|
args_(args) {
|
||||||
onrestart_.InitSingleTrigger("onrestart");
|
onrestart_.InitSingleTrigger("onrestart");
|
||||||
}
|
}
|
||||||
|
|
@ -491,6 +497,30 @@ bool Service::ParseOomScoreAdjust(const std::vector<std::string>& args, std::str
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Service::ParseMemcgSwappiness(const std::vector<std::string>& args, std::string* err) {
|
||||||
|
if (!ParseInt(args[1], &swappiness_, 0)) {
|
||||||
|
*err = "swappiness value must be equal or greater than 0";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Service::ParseMemcgLimitInBytes(const std::vector<std::string>& args, std::string* err) {
|
||||||
|
if (!ParseInt(args[1], &limit_in_bytes_, 0)) {
|
||||||
|
*err = "limit_in_bytes value must be equal or greater than 0";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Service::ParseMemcgSoftLimitInBytes(const std::vector<std::string>& args, std::string* err) {
|
||||||
|
if (!ParseInt(args[1], &soft_limit_in_bytes_, 0)) {
|
||||||
|
*err = "soft_limit_in_bytes value must be equal or greater than 0";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool Service::ParseSeclabel(const std::vector<std::string>& args, std::string* err) {
|
bool Service::ParseSeclabel(const std::vector<std::string>& args, std::string* err) {
|
||||||
seclabel_ = args[1];
|
seclabel_ = args[1];
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -609,6 +639,12 @@ const Service::OptionParserMap::Map& Service::OptionParserMap::map() const {
|
||||||
{"onrestart", {1, kMax, &Service::ParseOnrestart}},
|
{"onrestart", {1, kMax, &Service::ParseOnrestart}},
|
||||||
{"oom_score_adjust",
|
{"oom_score_adjust",
|
||||||
{1, 1, &Service::ParseOomScoreAdjust}},
|
{1, 1, &Service::ParseOomScoreAdjust}},
|
||||||
|
{"memcg.swappiness",
|
||||||
|
{1, 1, &Service::ParseMemcgSwappiness}},
|
||||||
|
{"memcg.soft_limit_in_bytes",
|
||||||
|
{1, 1, &Service::ParseMemcgSoftLimitInBytes}},
|
||||||
|
{"memcg.limit_in_bytes",
|
||||||
|
{1, 1, &Service::ParseMemcgLimitInBytes}},
|
||||||
{"namespace", {1, 2, &Service::ParseNamespace}},
|
{"namespace", {1, 2, &Service::ParseNamespace}},
|
||||||
{"seclabel", {1, 1, &Service::ParseSeclabel}},
|
{"seclabel", {1, 1, &Service::ParseSeclabel}},
|
||||||
{"setenv", {2, 2, &Service::ParseSetenv}},
|
{"setenv", {2, 2, &Service::ParseSetenv}},
|
||||||
|
|
@ -795,6 +831,24 @@ bool Service::Start() {
|
||||||
if (errno != 0) {
|
if (errno != 0) {
|
||||||
PLOG(ERROR) << "createProcessGroup(" << uid_ << ", " << pid_ << ") failed for service '"
|
PLOG(ERROR) << "createProcessGroup(" << uid_ << ", " << pid_ << ") failed for service '"
|
||||||
<< name_ << "'";
|
<< name_ << "'";
|
||||||
|
} else {
|
||||||
|
if (swappiness_ != -1) {
|
||||||
|
if (!setProcessGroupSwappiness(uid_, pid_, swappiness_)) {
|
||||||
|
PLOG(ERROR) << "setProcessGroupSwappiness failed";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (soft_limit_in_bytes_ != -1) {
|
||||||
|
if (!setProcessGroupSoftLimit(uid_, pid_, soft_limit_in_bytes_)) {
|
||||||
|
PLOG(ERROR) << "setProcessGroupSoftLimit failed";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (limit_in_bytes_ != -1) {
|
||||||
|
if (!setProcessGroupLimit(uid_, pid_, limit_in_bytes_)) {
|
||||||
|
PLOG(ERROR) << "setProcessGroupLimit failed";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((flags_ & SVC_EXEC) != 0) {
|
if ((flags_ & SVC_EXEC) != 0) {
|
||||||
|
|
|
||||||
|
|
@ -134,6 +134,9 @@ class Service {
|
||||||
bool ParseOneshot(const std::vector<std::string>& args, std::string* err);
|
bool ParseOneshot(const std::vector<std::string>& args, std::string* err);
|
||||||
bool ParseOnrestart(const std::vector<std::string>& args, std::string* err);
|
bool ParseOnrestart(const std::vector<std::string>& args, std::string* err);
|
||||||
bool ParseOomScoreAdjust(const std::vector<std::string>& args, std::string* err);
|
bool ParseOomScoreAdjust(const std::vector<std::string>& args, std::string* err);
|
||||||
|
bool ParseMemcgLimitInBytes(const std::vector<std::string>& args, std::string* err);
|
||||||
|
bool ParseMemcgSoftLimitInBytes(const std::vector<std::string>& args, std::string* err);
|
||||||
|
bool ParseMemcgSwappiness(const std::vector<std::string>& args, std::string* err);
|
||||||
bool ParseNamespace(const std::vector<std::string>& args, std::string* err);
|
bool ParseNamespace(const std::vector<std::string>& args, std::string* err);
|
||||||
bool ParseSeclabel(const std::vector<std::string>& args, std::string* err);
|
bool ParseSeclabel(const std::vector<std::string>& args, std::string* err);
|
||||||
bool ParseSetenv(const std::vector<std::string>& args, std::string* err);
|
bool ParseSetenv(const std::vector<std::string>& args, std::string* err);
|
||||||
|
|
@ -181,6 +184,10 @@ class Service {
|
||||||
|
|
||||||
int oom_score_adjust_;
|
int oom_score_adjust_;
|
||||||
|
|
||||||
|
int swappiness_;
|
||||||
|
int soft_limit_in_bytes_;
|
||||||
|
int limit_in_bytes_;
|
||||||
|
|
||||||
bool process_cgroup_empty_ = false;
|
bool process_cgroup_empty_ = false;
|
||||||
|
|
||||||
std::vector<std::string> args_;
|
std::vector<std::string> args_;
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,10 @@ int killProcessGroupOnce(uid_t uid, int initialPid, int signal);
|
||||||
|
|
||||||
int createProcessGroup(uid_t uid, int initialPid);
|
int createProcessGroup(uid_t uid, int initialPid);
|
||||||
|
|
||||||
|
bool setProcessGroupSwappiness(uid_t uid, int initialPid, int swappiness);
|
||||||
|
bool setProcessGroupSoftLimit(uid_t uid, int initialPid, int64_t softLimitInBytes);
|
||||||
|
bool setProcessGroupLimit(uid_t uid, int initialPid, int64_t limitInBytes);
|
||||||
|
|
||||||
void removeAllProcessGroups(void);
|
void removeAllProcessGroups(void);
|
||||||
|
|
||||||
__END_DECLS
|
__END_DECLS
|
||||||
|
|
|
||||||
|
|
@ -35,12 +35,15 @@
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
|
#include <android-base/file.h>
|
||||||
#include <android-base/logging.h>
|
#include <android-base/logging.h>
|
||||||
#include <android-base/unique_fd.h>
|
#include <android-base/unique_fd.h>
|
||||||
#include <private/android_filesystem_config.h>
|
#include <private/android_filesystem_config.h>
|
||||||
|
|
||||||
#include <processgroup/processgroup.h>
|
#include <processgroup/processgroup.h>
|
||||||
|
|
||||||
|
using android::base::WriteStringToFile;
|
||||||
|
|
||||||
using namespace std::chrono_literals;
|
using namespace std::chrono_literals;
|
||||||
|
|
||||||
#define MEM_CGROUP_PATH "/dev/memcg/apps"
|
#define MEM_CGROUP_PATH "/dev/memcg/apps"
|
||||||
|
|
@ -402,22 +405,40 @@ int createProcessGroup(uid_t uid, int initialPid)
|
||||||
|
|
||||||
strlcat(path, PROCESSGROUP_CGROUP_PROCS_FILE, sizeof(path));
|
strlcat(path, PROCESSGROUP_CGROUP_PROCS_FILE, sizeof(path));
|
||||||
|
|
||||||
int fd = open(path, O_WRONLY);
|
|
||||||
if (fd == -1) {
|
|
||||||
int ret = -errno;
|
|
||||||
PLOG(ERROR) << "Failed to open " << path;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
char pid[PROCESSGROUP_MAX_PID_LEN + 1] = {0};
|
|
||||||
int len = snprintf(pid, sizeof(pid), "%d", initialPid);
|
|
||||||
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
if (write(fd, pid, len) < 0) {
|
if (!WriteStringToFile(std::to_string(initialPid), path)) {
|
||||||
ret = -errno;
|
ret = -errno;
|
||||||
PLOG(ERROR) << "Failed to write '" << pid << "' to " << path;
|
PLOG(ERROR) << "Failed to write '" << initialPid << "' to " << path;
|
||||||
}
|
}
|
||||||
|
|
||||||
close(fd);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool setProcessGroupValue(uid_t uid, int pid, const char* fileName, int64_t value) {
|
||||||
|
char path[PROCESSGROUP_MAX_PATH_LEN] = {0};
|
||||||
|
if (strcmp(getCgroupRootPath(), MEM_CGROUP_PATH)) {
|
||||||
|
PLOG(ERROR) << "Memcg is not mounted." << path;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
convertUidPidToPath(path, sizeof(path), uid, pid);
|
||||||
|
strlcat(path, fileName, sizeof(path));
|
||||||
|
|
||||||
|
if (!WriteStringToFile(std::to_string(value), path)) {
|
||||||
|
PLOG(ERROR) << "Failed to write '" << value << "' to " << path;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool setProcessGroupSwappiness(uid_t uid, int pid, int swappiness) {
|
||||||
|
return setProcessGroupValue(uid, pid, "/memory.swappiness", swappiness);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool setProcessGroupSoftLimit(uid_t uid, int pid, int64_t soft_limit_in_bytes) {
|
||||||
|
return setProcessGroupValue(uid, pid, "/memory.soft_limit_in_bytes", soft_limit_in_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool setProcessGroupLimit(uid_t uid, int pid, int64_t limit_in_bytes) {
|
||||||
|
return setProcessGroupValue(uid, pid, "/memory.limit_in_bytes", limit_in_bytes);
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue