summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUnsung Lee <unsung.lee@samsung.com>2022-02-21 12:57:57 +0900
committerUnsung Lee <unsung.lee@samsung.com>2022-02-22 14:42:23 +0900
commit9bce0b3b5dba0246ccc998186b99f1c9208a9602 (patch)
treef3129df671220f80b9dd24dc52eb055bdfb80604
parent36a18bfd34cd83728aec5880f77c69e3014dcb2a (diff)
downloadresourced-9bce0b3b5dba0246ccc998186b99f1c9208a9602.tar.gz
resourced-9bce0b3b5dba0246ccc998186b99f1c9208a9602.tar.bz2
resourced-9bce0b3b5dba0246ccc998186b99f1c9208a9602.zip
Parse 'PerProcess' section
Change-Id: If58a8ef63fc88acdb3a9e726068b6697304b7e0f Signed-off-by: Unsung Lee <unsung.lee@samsung.com>
-rw-r--r--src/common/cgroup/cgroup.h2
-rw-r--r--src/common/config-parser.c297
-rw-r--r--src/common/config-parser.h38
-rw-r--r--src/common/proc-common.h31
-rw-r--r--src/common/util.h2
-rw-r--r--src/process/watchdog/proc-watchdog.c7
-rw-r--r--src/resource-limiter/memory/vmpressure-lowmem-handler.c2
-rw-r--r--src/resourced/main.c8
8 files changed, 377 insertions, 10 deletions
diff --git a/src/common/cgroup/cgroup.h b/src/common/cgroup/cgroup.h
index 7c43d0c9..877f6aa7 100644
--- a/src/common/cgroup/cgroup.h
+++ b/src/common/cgroup/cgroup.h
@@ -50,8 +50,6 @@ extern "C" {
#define CGROUP_PER_PROCESS_NAME ""
#define CGROUP_GROUP_NAME ""
-#define CGROUP_VIP_LIST_DIR RD_CONFIG_PATH"/limiter.conf.d"
-#define CGROUP_VIP_CONF_SUFFIX ".conf"
#define CGROUP_DEFAULT_USE_HIERARCHY false
/*
diff --git a/src/common/config-parser.c b/src/common/config-parser.c
index 566d9006..b6b85b5b 100644
--- a/src/common/config-parser.c
+++ b/src/common/config-parser.c
@@ -25,8 +25,303 @@
#include "util.h"
#include "trace.h"
#include "config-parser.h"
+#include "proc-common.h"
-#define MAX_SECTION 64
+#define MAX_SECTION 64
+#define CPU_INIT_PRIO 100
+
+static GSList *app_conf_info_list;
+static GSList *service_conf_info_list;
+
+static struct proc_conf_info* process_exist(const char *name, enum proc_type proc_type)
+{
+ GSList *iter;
+ bool found = false;
+ struct proc_conf_info *pci = NULL;
+
+ if (proc_type != APP_TYPE && proc_type != SERVICE_TYPE)
+ return pci;
+
+ gslist_for_each_item(iter,
+ proc_type == APP_TYPE ? app_conf_info_list : service_conf_info_list) {
+ pci = (struct proc_conf_info *)iter->data;
+ if (!strncmp(pci->name, name, strlen(name)+1)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found)
+ pci = NULL;
+
+ return pci;
+}
+
+static int vendor_config(struct parse_result *result, void *user_data)
+{
+ int *config_type = (int *)user_data;
+ static struct proc_conf_info *pci = NULL;
+
+ if (!result || !user_data)
+ return RESOURCED_ERROR_INVALID_PARAMETER;
+
+ if (strncmp(result->section, PER_PROCESS_SECTION_CONF, strlen(PER_PROCESS_SECTION_CONF)+1))
+ return RESOURCED_ERROR_NONE;
+
+ if (!strncmp(result->name, SERVICE_NAME_CONF, strlen(SERVICE_NAME_CONF)+1) ||
+ !strncmp(result->name, APP_NAME_CONF, strlen(APP_NAME_CONF)+1)) {
+ pci = process_exist(result->value, result->name[0] == 'A' ? APP_TYPE : SERVICE_TYPE);
+ if (pci == NULL) {
+ pci = (struct proc_conf_info *)calloc(1, sizeof(struct proc_conf_info));
+ if (pci == NULL) {
+ _E("Failed to allocate memory during parsing vendor configurations");
+ return RESOURCED_ERROR_OUT_OF_MEMORY;
+ }
+ if (result->name[0] == 'A') {
+ pci->proc_type = APP_TYPE;
+ app_conf_info_list = g_slist_prepend(app_conf_info_list, (gpointer)pci);
+ }
+ else {
+ pci->proc_type = SERVICE_TYPE;
+ service_conf_info_list = g_slist_prepend(service_conf_info_list, (gpointer)pci);
+ }
+ pci->mem_type = CGROUP_TOP;
+ pci->cpu_type = CGROUP_TOP;
+ pci->cpu_priority = CPU_INIT_PRIO;
+ strncpy(pci->name, result->value, sizeof(pci->name)-1);
+ }
+ }
+ else if (!strncmp(result->name, CPU_CGROUP_NAME_CONF, strlen(CPU_CGROUP_NAME_CONF)+1) &&
+ *config_type == LIMITER_CONFIG) {
+ if (!pci) {
+ _E("process configuration information pointer should not be NULL");
+ return RESOURCED_ERROR_FAIL;
+ }
+
+ if (!strncmp(result->value, CGROUP_VIP_VALUE_CONF,
+ strlen(CGROUP_VIP_VALUE_CONF) +1)) {
+ pci->cpu_type = CGROUP_VIP;
+ }
+ else if (!strncmp(result->value, CGROUP_HIGH_VALUE_CONF,
+ strlen(CGROUP_HIGH_VALUE_CONF) +1)) {
+ pci->cpu_type = CGROUP_HIGH;
+ }
+ else if (!strncmp(result->value, CGROUP_MEDIUM_VALUE_CONF,
+ strlen(CGROUP_MEDIUM_VALUE_CONF) +1)) {
+ pci->cpu_type = CGROUP_MEDIUM;
+ }
+ else if (!strncmp(result->value, CGROUP_LOW_VALUE_CONF,
+ strlen(CGROUP_LOW_VALUE_CONF) +1)) {
+ pci->cpu_type = CGROUP_LOW;
+ }
+ else {
+ _E("invalid parameter (%s)", result->value);
+ return RESOURCED_ERROR_INVALID_PARAMETER;
+ }
+ }
+ else if (!strncmp(result->name, MEM_CGROUP_NAME_CONF, strlen(MEM_CGROUP_NAME_CONF)+1) &&
+ *config_type == LIMITER_CONFIG) {
+ if (!pci) {
+ _E("process configuration information pointer should not be NULL");
+ return RESOURCED_ERROR_FAIL;
+ }
+
+ if (!strncmp(result->value, CGROUP_VIP_VALUE_CONF,
+ strlen(CGROUP_VIP_VALUE_CONF) +1)) {
+ pci->mem_type = CGROUP_VIP;
+ }
+ else if (!strncmp(result->value, CGROUP_HIGH_VALUE_CONF,
+ strlen(CGROUP_HIGH_VALUE_CONF) +1)) {
+ pci->mem_type = CGROUP_HIGH;
+ }
+ else if (!strncmp(result->value, CGROUP_MEDIUM_VALUE_CONF,
+ strlen(CGROUP_MEDIUM_VALUE_CONF) +1)) {
+ pci->mem_type = CGROUP_MEDIUM;
+ }
+ else if (!strncmp(result->value, CGROUP_LOW_VALUE_CONF,
+ strlen(CGROUP_LOW_VALUE_CONF) +1)) {
+ pci->mem_type = CGROUP_LOW;
+ }
+ else {
+ _E("invalid parameter (%s)", result->value);
+ return RESOURCED_ERROR_INVALID_PARAMETER;
+ }
+ }
+ else if (!strncmp(result->name, MEM_LIMIT_ACTION_NAME_CONF,
+ strlen(MEM_LIMIT_ACTION_NAME_CONF)+1) && *config_type == LIMITER_CONFIG) {
+ if (!pci) {
+ _E("process configuration information pointer should not be NULL");
+ return RESOURCED_ERROR_FAIL;
+ }
+
+ char *ptr = strchr(result->value, ',');
+ if (ptr == NULL) {
+ _E("Cannot find ',' in the string (%s)", result->value);
+ return RESOURCED_ERROR_FAIL;
+ }
+
+ char *second_value = ptr + 1;
+ char temp;
+
+ if (result->value > (ptr - 2)) {
+ _E("Size of string should be larger than 2");
+ return RESOURCED_ERROR_FAIL;
+ }
+
+ if (*(ptr - 1) == 'B') {
+ temp = *(ptr - 2);
+ *(ptr - 2) = '\0';
+
+ if (temp == 'G') {
+ pci->mem_action.memory = GBYTE_TO_MBYTE(atoi(result->value));
+ }
+ else if (temp == 'M') {
+ pci->mem_action.memory = atoi(result->value);
+ }
+ else if (temp == 'K') {
+ pci->mem_action.memory = KBYTE_TO_MBYTE(atoi(result->value));
+ }
+ else if (temp == ' ') {
+ pci->mem_action.memory = BYTE_TO_MBYTE(atoi(result->value));
+ }
+ else {
+ _E("Memory size unit should be GB or MB or KB or B");
+ return RESOURCED_ERROR_FAIL;
+ }
+
+ if (!strncmp(second_value, ACTION_BROADCAST_VALUE_CONF,
+ strlen(ACTION_BROADCAST_VALUE_CONF)+1))
+ pci->mem_action.action = PROC_ACTION_BROADCAST;
+ else if (!strncmp(second_value, ACTION_RECLAIM_VALUE_CONF,
+ strlen(ACTION_RECLAIM_VALUE_CONF)+1))
+ pci->mem_action.action = PROC_ACTION_RECLAIM;
+ else if (!strncmp(second_value, ACTION_KILL_VALUE_CONF,
+ strlen(ACTION_KILL_VALUE_CONF)+1))
+ pci->mem_action.action = PROC_ACTION_KILL;
+ else {
+ _E("action (%s) is not supported", second_value);
+ return RESOURCED_ERROR_FAIL;
+ }
+ }
+ else {
+ _E("Memory size unit should be XB");
+ return RESOURCED_ERROR_FAIL;
+ }
+ }
+ else if (!strncmp(result->name, CPU_PRIORITY_NAME_CONF, strlen(CPU_PRIORITY_NAME_CONF)+1) &&
+ *config_type == LIMITER_CONFIG) {
+ if (!pci) {
+ _E("process configuration information pointer should not be NULL");
+ return RESOURCED_ERROR_FAIL;
+ }
+ pci->cpu_priority = atoi(result->value);
+ }
+ else if (!strncmp(result->name, ACTION_ON_FAILURE_NAME_CONF,
+ strlen(ACTION_ON_FAILURE_NAME_CONF)+1) && *config_type == PROCESS_CONFIG) {
+ if (!pci) {
+ _E("process configuration information pointer should not be NULL");
+ return RESOURCED_ERROR_FAIL;
+ }
+
+ if (!strncmp(result->value, ACTION_REBOOT_VALUE_CONF,
+ strlen(ACTION_REBOOT_VALUE_CONF) +1)) {
+ pci->fail_action = PROC_ACTION_REBOOT;
+ }
+ else {
+ _E("invalid parameter (%s)", result->value);
+ return RESOURCED_ERROR_INVALID_PARAMETER;
+ }
+ }
+ else if (!strncmp(result->name, WATCHDOG_ACTION_NAME_CONF,
+ strlen(WATCHDOG_ACTION_NAME_CONF)+1) && *config_type == PROCESS_CONFIG) {
+ if (!pci) {
+ _E("process configuration information pointer should not be NULL");
+ return RESOURCED_ERROR_FAIL;
+ }
+
+ if (!strncmp(result->value, ACTION_IGNORE_VALUE_CONF,
+ strlen(ACTION_IGNORE_VALUE_CONF) +1)) {
+ pci->watchdog_action = PROC_ACTION_IGNORE;
+ }
+ else if (!strncmp(result->value, ACTION_KILL_VALUE_CONF,
+ strlen(ACTION_KILL_VALUE_CONF) +1)) {
+ pci->watchdog_action = PROC_ACTION_KILL;
+ }
+ else {
+ _E("invalid parameter (%s)", result->value);
+ return RESOURCED_ERROR_INVALID_PARAMETER;
+ }
+ }
+ else {
+ _E("Unknown configuration name (%s) and value (%s) on section (%s)",
+ result->name, result->value, result->section);
+ }
+
+ return RESOURCED_ERROR_NONE;
+}
+
+static void load_per_vendor_configs(const char *dir, int func(struct parse_result *result,
+ void *user_data), void *user_data)
+{
+ int count;
+ int idx;
+ struct dirent **namelist;
+
+ if ((count = scandir(dir, &namelist, NULL, alphasort)) == -1) {
+ _W("failed to opendir (%s)", dir);
+ return;
+ }
+
+ for (idx = 0; idx < count; idx++) {
+ char path[PATH_MAX] = {0, };
+
+ if (!strstr(namelist[idx]->d_name, CONF_FILE_SUFFIX))
+ continue;
+
+ snprintf(path, sizeof(path), "%s/%s", dir, namelist[idx]->d_name);
+ config_parse(path, func, user_data);
+ free(namelist[idx]);
+ }
+
+ free(namelist);
+}
+
+void resourced_parse_vendor_configs(void)
+{
+ int config_type;
+
+ config_type = LIMITER_CONFIG;
+ load_per_vendor_configs(CGROUP_VIP_LIST_DIR, vendor_config, &config_type);
+
+ config_type = PROCESS_CONFIG;
+ load_per_vendor_configs(PROC_CONF_DIR, vendor_config, &config_type);
+
+ //DEBUG
+ GSList *iter;
+ gslist_for_each_item(iter, service_conf_info_list) {
+ struct proc_conf_info *pci = (struct proc_conf_info *)iter->data;
+ _I("[CONFIG] name: %s", pci->name);
+ _I("[CONFIG] mem cgroup: %d", pci->mem_type);
+ _I("[CONFIG] cpu cgroup: %d", pci->cpu_type);
+ _I("[CONFIG] cpu priority: %d", pci->cpu_priority);
+ _I("[CONFIG] watchdog_flag: %x", pci->watchdog_action);
+ _I("[CONFIG] fail_flag: %x", pci->fail_action);
+ _I("[CONFIG] memory: %lu MB", pci->mem_action.memory);
+ _I("[CONFIG] action: %d", pci->mem_action.action);
+ }
+
+ gslist_for_each_item(iter, app_conf_info_list) {
+ struct proc_conf_info *pci = (struct proc_conf_info *)iter->data;
+ _I("[CONFIG] name: %s", pci->name);
+ _I("[CONFIG] mem cgroup: %d", pci->mem_type);
+ _I("[CONFIG] cpu cgroup: %d", pci->cpu_type);
+ _I("[CONFIG] cpu priority: %d", pci->cpu_priority);
+ _I("[CONFIG] watchdog_flag: %x", pci->watchdog_action);
+ _I("[CONFIG] fail_flag: %x", pci->fail_action);
+ _I("[CONFIG] memory: %lu MB", pci->mem_action.memory);
+ _I("[CONFIG] action: %d", pci->mem_action.action);
+ }
+}
int config_parse(const char *file_name, int cb(struct parse_result *result,
void *user_data), void *user_data)
diff --git a/src/common/config-parser.h b/src/common/config-parser.h
index 09ad5ca8..22deac1d 100644
--- a/src/common/config-parser.h
+++ b/src/common/config-parser.h
@@ -27,11 +27,46 @@
extern "C" {
#endif /* __cplusplus */
-#define PER_PROCESS_CONF "PerProcess"
+
+#define CONF_FILE_SUFFIX ".conf"
+
+#define CGROUP_VIP_LIST_DIR RD_CONFIG_PATH"/limiter.conf.d"
+#define PROC_CONF_DIR "/etc/resourced/process.conf.d"
+
+#define PER_PROCESS_SECTION_CONF "PerProcess"
+
+/* configuration name */
+#define SERVICE_NAME_CONF "Service"
+#define APP_NAME_CONF "App"
+#define CPU_CGROUP_NAME_CONF "CpuGroup"
+#define MEM_CGROUP_NAME_CONF "MemGroup"
+#define MEM_LIMIT_ACTION_NAME_CONF "MemLimitAction"
+#define CPU_PRIORITY_NAME_CONF "CpuPriority"
+#define ACTION_ON_FAILURE_NAME_CONF "ActionOnFailure"
+#define WATCHDOG_ACTION_NAME_CONF "WatchdogAction"
+
+/* configuration value */
+#define CGROUP_VIP_VALUE_CONF "vip"
+#define CGROUP_HIGH_VALUE_CONF "high"
+#define CGROUP_MEDIUM_VALUE_CONF "medium"
+#define CGROUP_LOW_VALUE_CONF "lowest"
+#define ACTION_BROADCAST_VALUE_CONF "broadcast"
+#define ACTION_RECLAIM_VALUE_CONF "reclaim"
+#define ACTION_KILL_VALUE_CONF "kill"
+#define ACTION_REBOOT_VALUE_CONF "reboot"
+#define ACTION_IGNORE_VALUE_CONF "ignore"
+
#define MATCH(a, b) (!strncmp(a, b, strlen(a) + 1) ? 1 : 0)
#define SET_CONF(a, b) (a = (b > 0.0 ? b : a))
+enum config_type {
+ LIMITER_CONFIG,
+ OPTIMIZER_CONFIG,
+ MONITOR_CONFIG,
+ PROCESS_CONFIG,
+};
+
struct parse_result {
char *section;
char *name;
@@ -86,6 +121,7 @@ int config_parse_float(const char *filename, unsigned line, const char *section,
int config_parse_long(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data);
int config_parse_strv(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data);
+void resourced_parse_vendor_configs(void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
diff --git a/src/common/proc-common.h b/src/common/proc-common.h
index 3c7951b0..76300575 100644
--- a/src/common/proc-common.h
+++ b/src/common/proc-common.h
@@ -44,6 +44,37 @@ extern "C" {
typedef GSList *pid_list;
+enum proc_action {
+ PROC_ACTION_KILL = 0x1,
+ PROC_ACTION_RECLAIM = 0x2,
+ PROC_ACTION_BROADCAST = 0x4,
+
+ PROC_ACTION_IGNORE = 0x8,
+
+ PROC_ACTION_REBOOT = 0x16,
+};
+
+enum proc_type {
+ APP_TYPE,
+ SERVICE_TYPE,
+};
+
+struct mem_action {
+ unsigned long memory; /* MB */
+ enum proc_action action;
+};
+
+struct proc_conf_info {
+ char name[PROC_NAME_MAX];
+ enum proc_type proc_type;
+ enum cgroup_type mem_type; /* fixed memory cgroup */
+ enum cgroup_type cpu_type; /* fixed cpu cgroup */
+ int cpu_priority; /* fixed cpu priority */
+ enum proc_action watchdog_action; /* watchdog action */
+ enum proc_action fail_action; /* release action */
+ struct mem_action mem_action;
+};
+
enum application_type {
PROC_TYPE_NONE,
PROC_TYPE_READY,
diff --git a/src/common/util.h b/src/common/util.h
index 3752ec13..affda261 100644
--- a/src/common/util.h
+++ b/src/common/util.h
@@ -88,6 +88,8 @@ static inline void closedirp(DIR **d)
#define MBYTE_TO_BYTE(m) ((m) << 20)
#define MBYTE_TO_KBYTE(m) ((m) << 10)
+#define GBYTE_TO_MBYTE(g) ((g) << 10)
+
#define streq(a, b) (strncmp((a), (b), strlen(b)+1) == 0)
#define strneq(a, b, n) (strncmp((a), (b), (n)) == 0)
#define strcaseeq(a, b) (strcasecmp((a), (b)) == 0)
diff --git a/src/process/watchdog/proc-watchdog.c b/src/process/watchdog/proc-watchdog.c
index 06cb48de..6903f29c 100644
--- a/src/process/watchdog/proc-watchdog.c
+++ b/src/process/watchdog/proc-watchdog.c
@@ -46,9 +46,6 @@
#include "module-data.h"
#include "dbus-handler.h"
-#define PROC_CONF_DIR "/etc/resourced/process.conf.d"
-#define PROC_CONF_SUFFIX ".conf"
-
#define SYSTEMD_DBUS_DEST "org.freedesktop.systemd1"
#define SYSTEMD_DBUS_UNIT_PATH "/org/freedesktop/systemd1/unit/"
#define SYSTEMD_DBUS_SERVICE_IFACE SYSTEMD_DBUS_DEST".Service"
@@ -258,7 +255,7 @@ static int proc_watchdog_load_config(struct parse_result *result, void *user_dat
if (!user_data)
return -1;
- if (!strstr(result->section, PER_PROCESS_CONF))
+ if (!strstr(result->section, PER_PROCESS_SECTION_CONF))
return -1;
snprintf(vgname, sizeof(vgname), "%s:%s", (char *)user_data, result->section);
@@ -420,7 +417,7 @@ static void proc_watchdog_load_configs(void)
for (idx = 0; idx < count; idx++) {
char path[PATH_MAX] = {0, };
- if (!strstr(namelist[idx]->d_name, PROC_CONF_SUFFIX))
+ if (!strstr(namelist[idx]->d_name, CONF_FILE_SUFFIX))
continue;
snprintf(path, sizeof(path), "%s/%s", PROC_CONF_DIR, namelist[idx]->d_name);
diff --git a/src/resource-limiter/memory/vmpressure-lowmem-handler.c b/src/resource-limiter/memory/vmpressure-lowmem-handler.c
index 36b46b0c..f3f6d997 100644
--- a/src/resource-limiter/memory/vmpressure-lowmem-handler.c
+++ b/src/resource-limiter/memory/vmpressure-lowmem-handler.c
@@ -2287,7 +2287,7 @@ static void load_per_vendor_configs(void)
for (idx = 0; idx < count; idx++) {
char path[PATH_MAX] = {0, };
- if (!strstr(namelist[idx]->d_name, CGROUP_VIP_CONF_SUFFIX))
+ if (!strstr(namelist[idx]->d_name, CONF_FILE_SUFFIX))
continue;
snprintf(path, sizeof(path), "%s/%s", CGROUP_VIP_LIST_DIR, namelist[idx]->d_name);
diff --git a/src/resourced/main.c b/src/resourced/main.c
index 0a5a847b..7a5dcbcf 100644
--- a/src/resourced/main.c
+++ b/src/resourced/main.c
@@ -32,6 +32,7 @@
#include "proc-monitor.h"
#include "trace.h"
#include "notifier.h"
+#include "config-parser.h"
#include <glib.h>
#include <mcheck.h>
@@ -50,6 +51,13 @@ int main(int argc, char **argv)
"Resourced initialization failed\n");
init_modules_arg(&darg);
modules_check_runtime_support(NULL);
+
+ /* parse vendor specific configuration files.
+ * resourced currently supports two dirs called limiter.conf.d and process.conf.d
+ * ex) /etc/resourced/xxx.d/yyy.conf
+ */
+ resourced_parse_vendor_configs();
+
if (resourced_restarted()) {
_I("Relaunched. Start to initialize and restore");
modules_init(NULL);