Merge "Add memcg related configs to init."

am: b84666cbc0

Change-Id: I437c5d05582c6a3cce632f92835ee91f419a7190
This commit is contained in:
Robert Benea 2017-07-19 01:01:27 +00:00 committed by android-build-merger
commit 7564622f88
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,
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>`
> Set shutdown behavior of the service process. When this is not specified,
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),
priority_(0),
oom_score_adjust_(-1000),
swappiness_(-1),
soft_limit_in_bytes_(-1),
limit_in_bytes_(-1),
args_(args) {
onrestart_.InitSingleTrigger("onrestart");
}
@ -196,6 +199,9 @@ Service::Service(const std::string& name, unsigned flags, uid_t uid, gid_t gid,
ioprio_pri_(0),
priority_(0),
oom_score_adjust_(-1000),
swappiness_(-1),
soft_limit_in_bytes_(-1),
limit_in_bytes_(-1),
args_(args) {
onrestart_.InitSingleTrigger("onrestart");
}
@ -491,6 +497,30 @@ bool Service::ParseOomScoreAdjust(const std::vector<std::string>& args, std::str
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) {
seclabel_ = args[1];
return true;
@ -609,6 +639,12 @@ const Service::OptionParserMap::Map& Service::OptionParserMap::map() const {
{"onrestart", {1, kMax, &Service::ParseOnrestart}},
{"oom_score_adjust",
{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}},
{"seclabel", {1, 1, &Service::ParseSeclabel}},
{"setenv", {2, 2, &Service::ParseSetenv}},
@ -795,6 +831,24 @@ bool Service::Start() {
if (errno != 0) {
PLOG(ERROR) << "createProcessGroup(" << uid_ << ", " << pid_ << ") failed for service '"
<< 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) {

View file

@ -134,6 +134,9 @@ class Service {
bool ParseOneshot(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 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 ParseSeclabel(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 swappiness_;
int soft_limit_in_bytes_;
int limit_in_bytes_;
bool process_cgroup_empty_ = false;
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);
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);
__END_DECLS

View file

@ -35,12 +35,15 @@
#include <set>
#include <thread>
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/unique_fd.h>
#include <private/android_filesystem_config.h>
#include <processgroup/processgroup.h>
using android::base::WriteStringToFile;
using namespace std::chrono_literals;
#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));
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;
if (write(fd, pid, len) < 0) {
if (!WriteStringToFile(std::to_string(initialPid), path)) {
ret = -errno;
PLOG(ERROR) << "Failed to write '" << pid << "' to " << path;
PLOG(ERROR) << "Failed to write '" << initialPid << "' to " << path;
}
close(fd);
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);
}