Merge "Add memcg related configs to init."

This commit is contained in:
Robert Benea 2017-07-19 00:54:41 +00:00 committed by Gerrit Code Review
commit b84666cbc0
5 changed files with 111 additions and 13 deletions

View file

@ -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.

View file

@ -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) {

View file

@ -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_;

View file

@ -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

View file

@ -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);
}