summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKichan Kwon <k_c.kwon@samsung.com>2016-11-05 15:01:39 +0900
committerKichan Kwon <k_c.kwon@samsung.com>2016-11-07 13:55:16 +0900
commit5bc59b709b475d6b8b33018c7bd966a096c54de0 (patch)
treeafcf9c2d5a5119c9a110d7aea1cc483c7c3d0071
parent0e3cd7effc4d56a6d6d53fc2ef4a5a60f406769a (diff)
downloadresourced-5bc59b709b475d6b8b33018c7bd966a096c54de0.tar.gz
resourced-5bc59b709b475d6b8b33018c7bd966a096c54de0.tar.bz2
resourced-5bc59b709b475d6b8b33018c7bd966a096c54de0.zip
common : add cgroup control functions
- Getting pid - Getting information about memory.stat - In addition, all cgroup functions will unify prefix Change-Id: I305ba00c5baa8e7962340d03c133cdc75faa3949 Signed-off-by: Kichan Kwon <k_c.kwon@samsung.com>
-rw-r--r--src/CMakeLists.txt2
-rw-r--r--src/common/cgroup-memory-stat-lookup.gperf119
-rw-r--r--src/common/cgroup.c204
-rw-r--r--src/common/cgroup.h88
-rw-r--r--src/cpu/cpu.c4
-rw-r--r--src/memory/vmpressure-lowmem-handler.c4
-rw-r--r--src/swap/swap.c12
-rw-r--r--src/timer-slack/timer-slack.c6
-rw-r--r--src/vip-agent/vip-process.c8
9 files changed, 410 insertions, 37 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index c853a25c..317945a4 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -15,9 +15,11 @@ INCLUDE(${CMAKE_SOURCE_DIR}/cmake/InstallSymlink.cmake)
INCLUDE(${CMAKE_SOURCE_DIR}/cmake/ProcessGPERF.cmake)
PROCESS_GPERF(${COMMON_SOURCE_DIR}/smaps-lookup.gperf ${COMMON_SOURCE_DIR}/smaps-lookup.c)
+PROCESS_GPERF(${COMMON_SOURCE_DIR}/cgroup-memory-stat-lookup.gperf ${COMMON_SOURCE_DIR}/cgroup-memory-stat-lookup.c)
PROCESS_GPERF(${COMMON_SOURCE_DIR}/meminfo-lookup.gperf ${COMMON_SOURCE_DIR}/meminfo-lookup.c)
SET(RESOURCED_SHARED_SOURCES ${RESOURCED_SHARED_SOURCES}
${COMMON_SOURCE_DIR}/smaps-lookup.c
+ ${COMMON_SOURCE_DIR}/cgroup-memory-stat-lookup.c
${COMMON_SOURCE_DIR}/meminfo-lookup.c
)
diff --git a/src/common/cgroup-memory-stat-lookup.gperf b/src/common/cgroup-memory-stat-lookup.gperf
new file mode 100644
index 00000000..6522b4b3
--- /dev/null
+++ b/src/common/cgroup-memory-stat-lookup.gperf
@@ -0,0 +1,119 @@
+%{
+#include <assert.h>
+#include <string.h>
+
+#include "cgroup.h"
+
+struct memory_stat_key {
+ const char* name;
+ enum cgroup_memory_stat_id id;
+};
+
+%}
+struct memory_stat_key;
+%language=C
+%define slot-name name
+%define hash-function-name cgroup_memory_stat_hash
+%define lookup-function-name cgroup_memory_stat_lookup
+%readonly-tables
+%omit-struct-type
+%struct-type
+%includes
+%%
+cache, CGROUP_MEMORY_STAT_CACHE
+rss, CGROUP_MEMORY_STAT_RSS
+rss_huge, CGROUP_MEMORY_STAT_RSS_HUGE
+mapped_file, CGROUP_MEMORY_STAT_MAPPED_FILE
+dirty, CGROUP_MEMORY_STAT_DIRTY
+writeback, CGROUP_MEMORY_STAT_WRITEBACK
+swap, CGROUP_MEMORY_STAT_SWAP
+pgpgin, CGROUP_MEMORY_STAT_PGPGIN
+pgpgout, CGROUP_MEMORY_STAT_PGPGOUT
+pgfault, CGROUP_MEMORY_STAT_PGFAULT
+pgmajfault, CGROUP_MEMORY_STAT_PGMAJFAULT
+inactive_anon, CGROUP_MEMORY_STAT_INACTIVE_ANON
+active_anon, CGROUP_MEMORY_STAT_ACTIVE_ANON
+inactive_file, CGROUP_MEMORY_STAT_INACTIVE_FILE
+active_file, CGROUP_MEMORY_STAT_ACTIVE_FILE
+unevictable, CGROUP_MEMORY_STAT_UNEVICTABLE
+hierarchical_memory_limit, CGROUP_MEMORY_STAT_HIERARCHICAL_MEMORY_LIMIT
+hierarchical_memsw_limit, CGROUP_MEMORY_STAT_HIERARCHICAL_MEMSW_LIMIT
+total_cache, CGROUP_MEMORY_STAT_TOTAL_CACHE
+total_rss, CGROUP_MEMORY_STAT_TOTAL_RSS
+total_rss_huge, CGROUP_MEMORY_STAT_TOTAL_RSS_HUGE
+total_mapped_file, CGROUP_MEMORY_STAT_TOTAL_MAPPED_FILE
+total_dirty, CGROUP_MEMORY_STAT_TOTAL_DIRTY
+total_writeback, CGROUP_MEMORY_STAT_TOTAL_WRITEBACK
+total_swap, CGROUP_MEMORY_STAT_TOTAL_SWAP
+total_pgpgin, CGROUP_MEMORY_STAT_TOTAL_PGPGIN
+total_pgpgout, CGROUP_MEMORY_STAT_TOTAL_PGPGOUT
+total_pgfault, CGROUP_MEMORY_STAT_TOTAL_PGFAULT
+total_pgmajfault, CGROUP_MEMORY_STAT_TOTAL_PGMAJFAULT
+total_inactive_anon, CGROUP_MEMORY_STAT_TOTAL_INACTIVE_ANON
+total_active_anon, CGROUP_MEMORY_STAT_TOTAL_ACTIVE_ANON
+total_inactive_file, CGROUP_MEMORY_STAT_TOTAL_INACTIVE_FILE
+total_active_file, CGROUP_MEMORY_STAT_TOTAL_ACTIVE_FILE
+total_unevictable, CGROUP_MEMORY_STAT_TOTAL_UNEVICTABLE
+recent_rotated_anon, CGROUP_MEMORY_STAT_RECENT_ROTATED_ANON
+recent_rotated_file, CGROUP_MEMORY_STAT_RECENT_ROTATED_FILE
+recent_scanned_anon, CGROUP_MEMORY_STAT_RECENT_SCANNED_ANON
+recent_scanned_file, CGROUP_MEMORY_STAT_RECENT_SCANNED_FILE
+%%
+static const char* const cgroup_memory_stat_str[CGROUP_MEMORY_STAT_MAX] = {
+ [CGROUP_MEMORY_STAT_CACHE] = "cache",
+ [CGROUP_MEMORY_STAT_RSS] = "rss",
+ [CGROUP_MEMORY_STAT_RSS_HUGE] = "rss_huge",
+ [CGROUP_MEMORY_STAT_MAPPED_FILE] = "mapped_file",
+ [CGROUP_MEMORY_STAT_DIRTY] = "dirty",
+ [CGROUP_MEMORY_STAT_WRITEBACK] = "writeback",
+ [CGROUP_MEMORY_STAT_SWAP] = "swap",
+ [CGROUP_MEMORY_STAT_PGPGIN] = "pgpgin",
+ [CGROUP_MEMORY_STAT_PGPGOUT] = "pgpgout",
+ [CGROUP_MEMORY_STAT_PGFAULT] = "pgfault",
+ [CGROUP_MEMORY_STAT_PGMAJFAULT] = "pgmajfault",
+ [CGROUP_MEMORY_STAT_INACTIVE_ANON] = "inactive_anon",
+ [CGROUP_MEMORY_STAT_ACTIVE_ANON] = "active_anon",
+ [CGROUP_MEMORY_STAT_INACTIVE_FILE] = "inactive_file",
+ [CGROUP_MEMORY_STAT_ACTIVE_FILE] = "active_file",
+ [CGROUP_MEMORY_STAT_UNEVICTABLE] = "unevictable",
+ [CGROUP_MEMORY_STAT_HIERARCHICAL_MEMORY_LIMIT] = "hierarchical_memory_limit",
+ [CGROUP_MEMORY_STAT_HIERARCHICAL_MEMSW_LIMIT] = "hierarchical_memsw_limit",
+ [CGROUP_MEMORY_STAT_TOTAL_CACHE] = "total_cache",
+ [CGROUP_MEMORY_STAT_TOTAL_RSS] = "total_rss",
+ [CGROUP_MEMORY_STAT_TOTAL_RSS_HUGE] = "total_rss_huge",
+ [CGROUP_MEMORY_STAT_TOTAL_MAPPED_FILE] = "total_mapped_file",
+ [CGROUP_MEMORY_STAT_TOTAL_DIRTY] = "total_dirty",
+ [CGROUP_MEMORY_STAT_TOTAL_WRITEBACK] = "total_writeback",
+ [CGROUP_MEMORY_STAT_TOTAL_SWAP] = "total_swap",
+ [CGROUP_MEMORY_STAT_TOTAL_PGPGIN] = "total_pgpgin",
+ [CGROUP_MEMORY_STAT_TOTAL_PGPGOUT] = "total_pgpgout",
+ [CGROUP_MEMORY_STAT_TOTAL_PGFAULT] = "total_pgfault",
+ [CGROUP_MEMORY_STAT_TOTAL_PGMAJFAULT] = "total_pgmajfault",
+ [CGROUP_MEMORY_STAT_TOTAL_INACTIVE_ANON] = "total_inactive_anon",
+ [CGROUP_MEMORY_STAT_TOTAL_ACTIVE_ANON] = "total_active_anon",
+ [CGROUP_MEMORY_STAT_TOTAL_INACTIVE_FILE] = "total_inactive_file",
+ [CGROUP_MEMORY_STAT_TOTAL_ACTIVE_FILE] = "total_active_file",
+ [CGROUP_MEMORY_STAT_TOTAL_UNEVICTABLE] = "total_unevictable",
+ [CGROUP_MEMORY_STAT_RECENT_ROTATED_ANON] = "recent_rotated_anon",
+ [CGROUP_MEMORY_STAT_RECENT_ROTATED_FILE] = "recent_rotated_file",
+ [CGROUP_MEMORY_STAT_RECENT_SCANNED_ANON] = "recent_scanned_anon",
+ [CGROUP_MEMORY_STAT_RECENT_SCANNED_FILE] = "recent_scanned_file"
+};
+
+const char *cgroup_memory_stat_id_to_string(enum cgroup_memory_stat_id id)
+{
+ assert(id >= 0 && id < CGROUP_MEMORY_STAT_MAX);
+
+ return cgroup_memory_stat_str[id];
+}
+
+enum cgroup_memory_stat_id cgroup_memory_stat_string_to_id(const char *str)
+{
+ const struct memory_stat_key *k;
+
+ assert(str);
+
+ k = cgroup_memory_stat_lookup(str, strlen(str));
+
+ return k ? k->id : CGROUP_MEMORY_STAT_INVALID;
+}
diff --git a/src/common/cgroup.c b/src/common/cgroup.c
index 90e869ce..180a5c8d 100644
--- a/src/common/cgroup.c
+++ b/src/common/cgroup.c
@@ -46,13 +46,13 @@
#define RELEASE_AGENT "/release_agent"
#define NOTIFY_ON_RELEASE "/notify_on_release"
-static bool is_cgroup_exists(const char *cgroup_full_path)
+static bool cgroup_is_exists(const char *cgroup_full_path)
{
struct stat stat_buf;
return stat(cgroup_full_path, &stat_buf) == 0;
}
-static int create_cgroup(const char *cgroup_full_path)
+static int cgroup_create(const char *cgroup_full_path)
{
if (mkdir(cgroup_full_path,
S_IRUSR | S_IWUSR | S_IRGRP) < 0)
@@ -65,7 +65,7 @@ static int create_cgroup(const char *cgroup_full_path)
* @desc place pid to cgroup.procs file
* @return 0 in case of success, errno value in case of failure
*/
-resourced_ret_c place_pid_to_cgroup_by_fullpath(const char *cgroup_full_path,
+resourced_ret_c cgroup_write_pid_fullpath(const char *cgroup_full_path,
const int pid)
{
char buf[256];
@@ -78,15 +78,15 @@ resourced_ret_c place_pid_to_cgroup_by_fullpath(const char *cgroup_full_path,
return RESOURCED_ERROR_NONE;
}
-resourced_ret_c place_pid_to_cgroup(const char *cgroup_subsystem,
+resourced_ret_c cgroup_write_pid(const char *cgroup_subsystem,
const char *cgroup_name, const int pid)
{
char buf[MAX_PATH_LENGTH];
snprintf(buf, sizeof(buf), "%s/%s", cgroup_subsystem, cgroup_name);
- return place_pid_to_cgroup_by_fullpath(buf, pid);
+ return cgroup_write_pid_fullpath(buf, pid);
}
-resourced_ret_c place_pidtree_to_cgroup(const char *cgroup_subsystem,
+resourced_ret_c cgroup_write_pidtree(const char *cgroup_subsystem,
const char *cgroup_name, const int pid)
{
char buf[MAX_PATH_LENGTH];
@@ -100,7 +100,7 @@ resourced_ret_c place_pidtree_to_cgroup(const char *cgroup_subsystem,
snprintf(buf, sizeof(buf), "%s/%s", cgroup_subsystem, cgroup_name);
/* place parent */
- ret = place_pid_to_cgroup_by_fullpath(buf, pid);
+ ret = cgroup_write_pid_fullpath(buf, pid);
ret_value_msg_if(ret != RESOURCED_ERROR_NONE, ret,
"Failed to put parent process %d into %s cgroup", pid, cgroup_name);
@@ -115,7 +115,7 @@ resourced_ret_c place_pidtree_to_cgroup(const char *cgroup_subsystem,
fclose(f);
return RESOURCED_ERROR_FAIL;
}
- resourced_ret_c ret = place_pid_to_cgroup_by_fullpath(buf, child_pid);
+ resourced_ret_c ret = cgroup_write_pid_fullpath(buf, child_pid);
if (ret != RESOURCED_ERROR_NONE) {
_E("Failed to put parent process %d into %s cgroup", pid, cgroup_name);
fclose(f);
@@ -155,7 +155,7 @@ int cgroup_read_node(const char *cgroup_name,
return ret;
}
-int make_cgroup_subdir(const char* parentdir, const char* cgroup_name, bool *already)
+int cgroup_make_subdir(const char* parentdir, const char* cgroup_name, bool *already)
{
char buf[MAX_PATH_LENGTH];
bool cgroup_exists;
@@ -171,7 +171,7 @@ int make_cgroup_subdir(const char* parentdir, const char* cgroup_name, bool *alr
ret_value_msg_if(ret > sizeof(buf), RESOURCED_ERROR_FAIL,
"Not enought buffer size for %s%s", parentdir, cgroup_name);
- cgroup_exists = is_cgroup_exists(buf);
+ cgroup_exists = cgroup_is_exists(buf);
if (!cgroup_exists) {
if (!strncmp(parentdir, DEFAULT_CGROUP, sizeof(DEFAULT_CGROUP))) {
ret = mount("tmpfs", DEFAULT_CGROUP, "tmpfs",
@@ -182,7 +182,7 @@ int make_cgroup_subdir(const char* parentdir, const char* cgroup_name, bool *alr
}
}
- ret = create_cgroup(buf);
+ ret = cgroup_create(buf);
ret_value_msg_if(ret < 0, RESOURCED_ERROR_FAIL,
"Fail to create cgroup %s : err %d", cgroup_name, errno);
@@ -200,13 +200,13 @@ int make_cgroup_subdir(const char* parentdir, const char* cgroup_name, bool *alr
return RESOURCED_ERROR_NONE;
}
-int mount_cgroup_subsystem(char* source, char* mount_point, char* opts)
+int cgroup_mount_subsystem(char* source, char* mount_point, char* opts)
{
return mount(source, mount_point, "cgroup",
MS_NODEV | MS_NOSUID | MS_NOEXEC, opts);
}
-int set_release_agent(const char *cgroup_subsys, const char *release_agent)
+int cgroup_set_release_agent(const char *cgroup_subsys, const char *release_agent)
{
_cleanup_free_ char *buf = NULL;
int r;
@@ -221,3 +221,181 @@ int set_release_agent(const char *cgroup_subsys, const char *release_agent)
return cgroup_write_node_str(buf, NOTIFY_ON_RELEASE, "1");
}
+
+int cgroup_pid_get_path(const char *controller, pid_t pid, char **path)
+{
+ _cleanup_free_ char *pid_cgroup = NULL;
+ _cleanup_fclose_ FILE *f = NULL;
+ char buf[LINE_MAX];
+ int r;
+
+ assert(controller);
+ assert(pid >= 0);
+ assert(path);
+
+ if (pid)
+ r = asprintf(&pid_cgroup, "/proc/%d/cgroup", pid);
+ else
+ r = asprintf(&pid_cgroup, "/proc/self/cgroup");
+ if (r < 0)
+ return -ENOMEM;
+
+ f = fopen(pid_cgroup, "re");
+ if (!f)
+ return -errno;
+
+ for (;;) {
+ _cleanup_free_ char *subsys = NULL, *p = NULL;
+ int n, id;
+
+ if (!fgets(buf, sizeof(buf), f)) {
+ if (ferror(f))
+ return -errno;
+
+ return -ENXIO;
+ }
+
+ n = sscanf(buf, "%d:%m[^:]:%ms", &id, &subsys, &p);
+ if (n != 3)
+ continue;
+
+ if ((streq(subsys, controller)) ||
+ (strneq(subsys, "name=", strlen("name=")) &&
+ streq(subsys + strlen("name="), controller))) {
+ *path = strdup(p);
+
+ if (!*path)
+ return -ENOMEM;
+
+ break;
+ }
+ }
+
+ return 0;
+}
+
+int cgroup_get_pids(const char *name, GArray **pids)
+{
+ _cleanup_free_ char *cg_procs = NULL;
+ _cleanup_fclose_ FILE *f = NULL;
+ char buf[MAX_PATH_LENGTH] = "";
+ GArray *array;
+ pid_t pid;
+
+ assert(name);
+ assert(pids);
+ assert(!pids);
+
+ if (asprintf(&cg_procs, "%s/cgroup.procs", name) < 0)
+ return -ENOMEM;
+
+ f = fopen(cg_procs, "r");
+ if (!f) {
+ _E("Failed to open '%s': %m", name);
+ return -errno;
+ }
+
+ array = g_array_new(false, false, sizeof(pid_t));
+
+ while (fgets(buf, 32, f)) {
+ pid = atoi(buf);
+ g_array_append_val(array, pid);
+ }
+
+ *pids = array;
+
+ return 0;
+}
+
+static void cgroup_memory_stat_init(struct cgroup_memory_stat *mem_stat, long long val)
+{
+ enum cgroup_memory_stat_id id;
+
+ assert(mem_stat);
+
+ for (id = 0; id < CGROUP_MEMORY_STAT_MAX; id++)
+ mem_stat->value[id] = val;
+}
+
+int cgroup_get_memory_stat(const char *name, struct cgroup_memory_stat **mem_stat)
+{
+ _cleanup_fclose_ FILE *f = NULL;
+ struct cgroup_memory_stat *st;
+ char p[PATH_MAX] = "";
+ char buf[LINE_MAX];
+ const char *memory_stat = "memory.stat";
+ const int memory_stat_len = strlen(memory_stat);
+
+ if (name) {
+ int l;
+ int name_len = strlen(name);
+
+ if (strneq(name, CGROUP_MEMORY, strlen(CGROUP_MEMORY)))
+ l = snprintf(p, PATH_MAX, "%s", name);
+ else
+ l = snprintf(p, PATH_MAX, "%s%s%s",
+ CGROUP_MEMORY,
+ name[0] != '/' ? "/" : "",
+ name);
+
+ if (name_len >= memory_stat_len &&
+ memcmp(name + name_len - memory_stat_len, memory_stat, memory_stat_len))
+ snprintf(p + l, PATH_MAX - l, "%s%s",
+ p[l - 1] != '/' ? "/" : "",
+ memory_stat);
+ } else
+ snprintf(p, PATH_MAX, "%s/%s", CGROUP_MEMORY, memory_stat);
+
+ f = fopen(p, "re");
+ if (!f)
+ return -errno;
+
+ st = (struct cgroup_memory_stat *)malloc(sizeof(struct cgroup_memory_stat));
+ if (!st)
+ return -ENOMEM;
+
+ cgroup_memory_stat_init(st, -1);
+
+ for (;;) {
+ enum cgroup_memory_stat_id id;
+ size_t l;
+
+ if (!fgets(buf, sizeof(buf), f)) {
+ if (ferror(f)) {
+ free(st);
+ return -errno;
+ }
+ break;
+ }
+
+ l = strcspn(buf, " ");
+ if (!l)
+ break;
+
+ buf[l] = 0;
+
+ id = cgroup_memory_stat_string_to_id(buf);
+ if (id < 0 || id >= CGROUP_MEMORY_STAT_MAX)
+ continue;
+
+ st->value[id] = atoll(buf + l + 1);
+ }
+
+ *mem_stat = st;
+
+ return 0;
+}
+
+/*
+ * Usage example:
+ * int i;
+ * pid_t pid;
+ * GArray *pids_array = NULL;
+ *
+ * cgroup_get_pids(name, &pids_array);
+ *
+ * for (i=0; i < pids_array->len; i++)
+ * _D("pid_t: %d", g_array_index(pids_array, pid_t, i));
+ * g_array_free(pids_array, TRUE);
+ *
+ */
diff --git a/src/common/cgroup.h b/src/common/cgroup.h
index eafcf5f6..2cb67e4b 100644
--- a/src/common/cgroup.h
+++ b/src/common/cgroup.h
@@ -19,6 +19,7 @@
#include <resourced.h>
#include <sys/types.h>
+#include <glib.h>
/*
* Cgroup creation interface
@@ -28,6 +29,8 @@
#define _CGROUP_LIBRARY_CGROUP_H_
#define DEFAULT_CGROUP "/sys/fs/cgroup"
+#define CGROUP_CPU DEFAULT_CGROUP "/cpu"
+#define CGROUP_MEMORY DEFAULT_CGROUP "/memory"
#define PROC_TASK_CHILDREN "/proc/%d/task/%d/children"
/**
@@ -67,7 +70,7 @@ int cgroup_write_node_str(const char *cgroup_name,
* as formal argument, in this case it will not be filled
* @return negative value if error
*/
-int make_cgroup_subdir(const char* parentdir, const char* cgroup_name, bool *already);
+int cgroup_make_subdir(const char* parentdir, const char* cgroup_name, bool *already);
/**
* @desc mount cgroup,
@@ -76,7 +79,7 @@ int make_cgroup_subdir(const char* parentdir, const char* cgroup_name, bool *alr
* @param opts - mount options
* @return negative value if error
*/
-int mount_cgroup_subsystem(char* source, char* mount_point, char* opts);
+int cgroup_mount_subsystem(char* source, char* mount_point, char* opts);
/**
* @desc write pid into cgroup_subsystem/cgroup_name file,
@@ -84,17 +87,17 @@ int mount_cgroup_subsystem(char* source, char* mount_point, char* opts);
* @param cgroup_name - name in /sys/fs/cgroup/subsystem/
* @return negative value if error
*/
-resourced_ret_c place_pid_to_cgroup(const char *cgroup_subsystem,
+resourced_ret_c cgroup_write_pid(const char *cgroup_subsystem,
const char *cgroup_name, const int pid);
-resourced_ret_c place_pid_to_cgroup_by_fullpath(const char *cgroup_full_path,
+resourced_ret_c cgroup_write_pid_fullpath(const char *cgroup_full_path,
const int pid);
/**
- * @desc doing the same as @see place_pid_to_cgroup,
+ * @desc doing the same as @see cgroup_write_pid,
* but also put into cgroup first level child processes
*/
-resourced_ret_c place_pidtree_to_cgroup(const char *cgroup_subsystem,
+resourced_ret_c cgroup_write_pidtree(const char *cgroup_subsystem,
const char *cgroup_name, const int pid);
/**
@@ -105,6 +108,77 @@ resourced_ret_c place_pidtree_to_cgroup(const char *cgroup_subsystem,
* @param release_agent full path to release agent executable
* @return negative value if error
*/
-int set_release_agent(const char *cgroup_subsys, const char *release_agent);
+int cgroup_set_release_agent(const char *cgroup_subsys, const char *release_agent);
+
+/**
+ * @desc get controller path of pid
+ * @param controller the name of control group such like
+ * "cpuacct,cpu", memory, freezer or debug. Especially supporting
+ * "name=" prefix. For example, if "systemd" is given as controller
+ * then finding also "name=systemd".
+ * @param pid pid to get the controller path
+ * @param path contoller path is filled. This value has to be free-ed
+ * by caller function.
+ * @return negative value if error
+ */
+int cgroup_pid_get_path(const char *controller, pid_t pid, char **path);
+
+/**
+ * @desc get PIDs of processes in a certain cgroup, an allocated array must be provided
+ * @return 0 if pids were read and array filled
+ */
+int cgroup_get_pids(const char *name, GArray **pids);
+
+enum cgroup_memory_stat_id {
+ CGROUP_MEMORY_STAT_CACHE = 0,
+ CGROUP_MEMORY_STAT_RSS,
+ CGROUP_MEMORY_STAT_RSS_HUGE,
+ CGROUP_MEMORY_STAT_MAPPED_FILE,
+ CGROUP_MEMORY_STAT_DIRTY,
+ CGROUP_MEMORY_STAT_WRITEBACK,
+ CGROUP_MEMORY_STAT_SWAP,
+ CGROUP_MEMORY_STAT_PGPGIN,
+ CGROUP_MEMORY_STAT_PGPGOUT,
+ CGROUP_MEMORY_STAT_PGFAULT,
+ CGROUP_MEMORY_STAT_PGMAJFAULT,
+ CGROUP_MEMORY_STAT_INACTIVE_ANON,
+ CGROUP_MEMORY_STAT_ACTIVE_ANON,
+ CGROUP_MEMORY_STAT_INACTIVE_FILE,
+ CGROUP_MEMORY_STAT_ACTIVE_FILE,
+ CGROUP_MEMORY_STAT_UNEVICTABLE,
+ CGROUP_MEMORY_STAT_HIERARCHICAL_MEMORY_LIMIT,
+ CGROUP_MEMORY_STAT_HIERARCHICAL_MEMSW_LIMIT,
+ CGROUP_MEMORY_STAT_TOTAL_CACHE,
+ CGROUP_MEMORY_STAT_TOTAL_RSS,
+ CGROUP_MEMORY_STAT_TOTAL_RSS_HUGE,
+ CGROUP_MEMORY_STAT_TOTAL_MAPPED_FILE,
+ CGROUP_MEMORY_STAT_TOTAL_DIRTY,
+ CGROUP_MEMORY_STAT_TOTAL_WRITEBACK,
+ CGROUP_MEMORY_STAT_TOTAL_SWAP,
+ CGROUP_MEMORY_STAT_TOTAL_PGPGIN,
+ CGROUP_MEMORY_STAT_TOTAL_PGPGOUT,
+ CGROUP_MEMORY_STAT_TOTAL_PGFAULT,
+ CGROUP_MEMORY_STAT_TOTAL_PGMAJFAULT,
+ CGROUP_MEMORY_STAT_TOTAL_INACTIVE_ANON,
+ CGROUP_MEMORY_STAT_TOTAL_ACTIVE_ANON,
+ CGROUP_MEMORY_STAT_TOTAL_INACTIVE_FILE,
+ CGROUP_MEMORY_STAT_TOTAL_ACTIVE_FILE,
+ CGROUP_MEMORY_STAT_TOTAL_UNEVICTABLE,
+ CGROUP_MEMORY_STAT_RECENT_ROTATED_ANON,
+ CGROUP_MEMORY_STAT_RECENT_ROTATED_FILE,
+ CGROUP_MEMORY_STAT_RECENT_SCANNED_ANON,
+ CGROUP_MEMORY_STAT_RECENT_SCANNED_FILE,
+ CGROUP_MEMORY_STAT_MAX,
+ CGROUP_MEMORY_STAT_INVALID = -1,
+};
+
+struct cgroup_memory_stat {
+ long long value[CGROUP_MEMORY_STAT_MAX];
+};
+
+const char *cgroup_memory_stat_id_to_string(enum cgroup_memory_stat_id id);
+enum cgroup_memory_stat_id cgroup_memory_stat_string_to_id(const char *str);
+
+int cgroup_get_memory_stat(const char *name, struct cgroup_memory_stat **mem_stat);
#endif /*_CGROUP_LIBRARY_CGROUP_H_*/
diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c
index c1d337ba..8f929ee5 100644
--- a/src/cpu/cpu.c
+++ b/src/cpu/cpu.c
@@ -387,11 +387,11 @@ static int resourced_cpu_init(void *data)
int ret_code;
_D("resourced_cpu_init");
- ret_code = make_cgroup_subdir(CPU_DEFAULT_CGROUP, "background", NULL);
+ ret_code = cgroup_make_subdir(CPU_DEFAULT_CGROUP, "background", NULL);
ret_value_msg_if(ret_code < 0, ret_code, "cpu init failed\n");
cpu_check_cpuquota();
if (cpu_quota_enabled()) {
- ret_code = make_cgroup_subdir(CPU_DEFAULT_CGROUP, "quota", NULL);
+ ret_code = cgroup_make_subdir(CPU_DEFAULT_CGROUP, "quota", NULL);
ret_value_msg_if(ret_code < 0, ret_code, "create service cgroup failed\n");
}
config_parse(CPU_CONF_FILE, load_cpu_config, NULL);
diff --git a/src/memory/vmpressure-lowmem-handler.c b/src/memory/vmpressure-lowmem-handler.c
index bd365d23..e55a74e3 100644
--- a/src/memory/vmpressure-lowmem-handler.c
+++ b/src/memory/vmpressure-lowmem-handler.c
@@ -1715,7 +1715,7 @@ static int create_memcgs(void)
continue;
mi = memcg_tree[i]->info;
name = mi->name;
- ret = make_cgroup_subdir(LOWMEM_DEFAULT_CGROUP, memcg_name[i], NULL);
+ ret = cgroup_make_subdir(LOWMEM_DEFAULT_CGROUP, memcg_name[i], NULL);
_D("Create subcgroup of memory : name = %s, ret = %d", memcg_name[i], ret);
if (!memcg_tree[i]->use_hierarchy)
continue;
@@ -1725,7 +1725,7 @@ static int create_memcgs(void)
name = strstr(mi->name, memcg_name[i]) + strlen(memcg_name[i]) + 1;
snprintf(parent_dir, MAX_PATH_LENGTH,
"%s/%s", LOWMEM_DEFAULT_CGROUP, memcg_name[i]);
- ret = make_cgroup_subdir(parent_dir, name, NULL);
+ ret = cgroup_make_subdir(parent_dir, name, NULL);
_D("Create subcgroup of memory/%s : name = %s, ret = %d", memcg_name[i], name, ret);
}
}
diff --git a/src/swap/swap.c b/src/swap/swap.c
index 4123a534..1b2460fe 100644
--- a/src/swap/swap.c
+++ b/src/swap/swap.c
@@ -231,12 +231,12 @@ static int swap_move_to_cgroup_by_pid(enum memcg_type type, pid_t pid)
mi = memcg_swap->info;
if (!pai)
- return place_pid_to_cgroup_by_fullpath(mi->name, pid);
+ return cgroup_write_pid_fullpath(mi->name, pid);
- ret = place_pid_to_cgroup_by_fullpath(mi->name, pai->main_pid);
+ ret = cgroup_write_pid_fullpath(mi->name, pai->main_pid);
gslist_for_each_item(iter_child, pai->childs) {
pid_t child = GPOINTER_TO_PID(iter_child->data);
- ret = place_pid_to_cgroup_by_fullpath(mi->name, child);
+ ret = cgroup_write_pid_fullpath(mi->name, child);
}
pai->memory.memcg_idx = MEMCG_SWAP;
pai->memory.memcg_info = mi;
@@ -256,10 +256,10 @@ static int swap_move_to_cgroup(struct memcg_info *info, GArray *candidates)
for (index = 0; index < candidates->len; index++) {
tsk = g_array_index(candidates, struct swap_task, index);
pai = tsk.pai;
- place_pid_to_cgroup_by_fullpath(info->name, pai->main_pid);
+ cgroup_write_pid_fullpath(info->name, pai->main_pid);
gslist_for_each_item(iter_child, pai->childs) {
pid_t child = GPOINTER_TO_PID(iter_child->data);
- place_pid_to_cgroup_by_fullpath(info->name, child);
+ cgroup_write_pid_fullpath(info->name, child);
}
pai->memory.memcg_idx = MEMCG_SWAP;
pai->memory.memcg_info = info;
@@ -1020,7 +1020,7 @@ static int resourced_swap_init(void *data)
{
int ret;
- make_cgroup_subdir(MEMCG_PATH, "swap", NULL);
+ cgroup_make_subdir(MEMCG_PATH, "swap", NULL);
resourced_swap_change_memcg_settings(MEMCG_SWAP);
resourced_swap_change_memcg_settings(MEMCG_FAVORITE);
resourced_swap_change_memcg_settings(MEMCG_PLATFORM);
diff --git a/src/timer-slack/timer-slack.c b/src/timer-slack/timer-slack.c
index 969462c3..43518a10 100644
--- a/src/timer-slack/timer-slack.c
+++ b/src/timer-slack/timer-slack.c
@@ -211,9 +211,9 @@ static int load_timer_config(struct parse_result *result, void *user_data)
static void timer_slack_cgroup_init(void)
{
- make_cgroup_subdir(TIMER_CGROUP_PATH, TIMER_EXCLUDE_CGROUP, NULL);
- make_cgroup_subdir(TIMER_CGROUP_PATH, TIMER_SERVICE_CGROUP, NULL);
- make_cgroup_subdir(TIMER_CGROUP_PATH, TIMER_BACKGRD_CGROUP, NULL);
+ cgroup_make_subdir(TIMER_CGROUP_PATH, TIMER_EXCLUDE_CGROUP, NULL);
+ cgroup_make_subdir(TIMER_CGROUP_PATH, TIMER_SERVICE_CGROUP, NULL);
+ cgroup_make_subdir(TIMER_CGROUP_PATH, TIMER_BACKGRD_CGROUP, NULL);
config_parse(TIMER_CONF_FILE, load_timer_config, NULL);
set_default_cgroup_value();
diff --git a/src/vip-agent/vip-process.c b/src/vip-agent/vip-process.c
index d2a4bbd6..3ed905e1 100644
--- a/src/vip-agent/vip-process.c
+++ b/src/vip-agent/vip-process.c
@@ -99,7 +99,7 @@ static int vip_create_sub_cgroup(const char *name, pid_t pid)
assert(name);
assert(pid);
- r = make_cgroup_subdir(VIP_CGROUP, name, &already);
+ r = cgroup_make_subdir(VIP_CGROUP, name, &already);
if (r < 0) {
_E("failed to create vip sub dir");
return r;
@@ -224,20 +224,20 @@ static int resourced_vip_process_init(void *data)
return RESOURCED_ERROR_NONE;
if (!is_mounted(VIP_CGROUP)) {
- r = make_cgroup_subdir(DEFAULT_CGROUP, "vip", NULL);
+ r = cgroup_make_subdir(DEFAULT_CGROUP, "vip", NULL);
if (r < 0) {
_E("failed to make vip cgroup");
return RESOURCED_ERROR_FAIL;
}
- r = mount_cgroup_subsystem("vip_cgroup", VIP_CGROUP,
+ r = cgroup_mount_subsystem("vip_cgroup", VIP_CGROUP,
"none,name=vip_cgroup");
if (r < 0) {
_E("failed to mount vip cgroup: %m");
return RESOURCED_ERROR_FAIL;
}
- r = set_release_agent("vip", "/usr/bin/vip-release-agent");
+ r = cgroup_set_release_agent("vip", "/usr/bin/vip-release-agent");
if (r < 0) {
_E("failed to set vip release agent: %s", strerror_r(-r, buf, sizeof(buf)));
return RESOURCED_ERROR_FAIL;