diff options
Diffstat (limited to 'fs/proc/base.c')
-rw-r--r-- | fs/proc/base.c | 94 |
1 files changed, 90 insertions, 4 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c index 5949d0ac30f2..f923b728388a 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -63,6 +63,7 @@ | |||
63 | #include <linux/namei.h> | 63 | #include <linux/namei.h> |
64 | #include <linux/mnt_namespace.h> | 64 | #include <linux/mnt_namespace.h> |
65 | #include <linux/mm.h> | 65 | #include <linux/mm.h> |
66 | #include <linux/swap.h> | ||
66 | #include <linux/rcupdate.h> | 67 | #include <linux/rcupdate.h> |
67 | #include <linux/kallsyms.h> | 68 | #include <linux/kallsyms.h> |
68 | #include <linux/stacktrace.h> | 69 | #include <linux/stacktrace.h> |
@@ -430,12 +431,11 @@ static const struct file_operations proc_lstats_operations = { | |||
430 | static int proc_oom_score(struct task_struct *task, char *buffer) | 431 | static int proc_oom_score(struct task_struct *task, char *buffer) |
431 | { | 432 | { |
432 | unsigned long points = 0; | 433 | unsigned long points = 0; |
433 | struct timespec uptime; | ||
434 | 434 | ||
435 | do_posix_clock_monotonic_gettime(&uptime); | ||
436 | read_lock(&tasklist_lock); | 435 | read_lock(&tasklist_lock); |
437 | if (pid_alive(task)) | 436 | if (pid_alive(task)) |
438 | points = badness(task, NULL, NULL, uptime.tv_sec); | 437 | points = oom_badness(task, NULL, NULL, |
438 | totalram_pages + total_swap_pages); | ||
439 | read_unlock(&tasklist_lock); | 439 | read_unlock(&tasklist_lock); |
440 | return sprintf(buffer, "%lu\n", points); | 440 | return sprintf(buffer, "%lu\n", points); |
441 | } | 441 | } |
@@ -1038,7 +1038,15 @@ static ssize_t oom_adjust_write(struct file *file, const char __user *buf, | |||
1038 | } | 1038 | } |
1039 | 1039 | ||
1040 | task->signal->oom_adj = oom_adjust; | 1040 | task->signal->oom_adj = oom_adjust; |
1041 | 1041 | /* | |
1042 | * Scale /proc/pid/oom_score_adj appropriately ensuring that a maximum | ||
1043 | * value is always attainable. | ||
1044 | */ | ||
1045 | if (task->signal->oom_adj == OOM_ADJUST_MAX) | ||
1046 | task->signal->oom_score_adj = OOM_SCORE_ADJ_MAX; | ||
1047 | else | ||
1048 | task->signal->oom_score_adj = (oom_adjust * OOM_SCORE_ADJ_MAX) / | ||
1049 | -OOM_DISABLE; | ||
1042 | unlock_task_sighand(task, &flags); | 1050 | unlock_task_sighand(task, &flags); |
1043 | put_task_struct(task); | 1051 | put_task_struct(task); |
1044 | 1052 | ||
@@ -1051,6 +1059,82 @@ static const struct file_operations proc_oom_adjust_operations = { | |||
1051 | .llseek = generic_file_llseek, | 1059 | .llseek = generic_file_llseek, |
1052 | }; | 1060 | }; |
1053 | 1061 | ||
1062 | static ssize_t oom_score_adj_read(struct file *file, char __user *buf, | ||
1063 | size_t count, loff_t *ppos) | ||
1064 | { | ||
1065 | struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode); | ||
1066 | char buffer[PROC_NUMBUF]; | ||
1067 | int oom_score_adj = OOM_SCORE_ADJ_MIN; | ||
1068 | unsigned long flags; | ||
1069 | size_t len; | ||
1070 | |||
1071 | if (!task) | ||
1072 | return -ESRCH; | ||
1073 | if (lock_task_sighand(task, &flags)) { | ||
1074 | oom_score_adj = task->signal->oom_score_adj; | ||
1075 | unlock_task_sighand(task, &flags); | ||
1076 | } | ||
1077 | put_task_struct(task); | ||
1078 | len = snprintf(buffer, sizeof(buffer), "%d\n", oom_score_adj); | ||
1079 | return simple_read_from_buffer(buf, count, ppos, buffer, len); | ||
1080 | } | ||
1081 | |||
1082 | static ssize_t oom_score_adj_write(struct file *file, const char __user *buf, | ||
1083 | size_t count, loff_t *ppos) | ||
1084 | { | ||
1085 | struct task_struct *task; | ||
1086 | char buffer[PROC_NUMBUF]; | ||
1087 | unsigned long flags; | ||
1088 | long oom_score_adj; | ||
1089 | int err; | ||
1090 | |||
1091 | memset(buffer, 0, sizeof(buffer)); | ||
1092 | if (count > sizeof(buffer) - 1) | ||
1093 | count = sizeof(buffer) - 1; | ||
1094 | if (copy_from_user(buffer, buf, count)) | ||
1095 | return -EFAULT; | ||
1096 | |||
1097 | err = strict_strtol(strstrip(buffer), 0, &oom_score_adj); | ||
1098 | if (err) | ||
1099 | return -EINVAL; | ||
1100 | if (oom_score_adj < OOM_SCORE_ADJ_MIN || | ||
1101 | oom_score_adj > OOM_SCORE_ADJ_MAX) | ||
1102 | return -EINVAL; | ||
1103 | |||
1104 | task = get_proc_task(file->f_path.dentry->d_inode); | ||
1105 | if (!task) | ||
1106 | return -ESRCH; | ||
1107 | if (!lock_task_sighand(task, &flags)) { | ||
1108 | put_task_struct(task); | ||
1109 | return -ESRCH; | ||
1110 | } | ||
1111 | if (oom_score_adj < task->signal->oom_score_adj && | ||
1112 | !capable(CAP_SYS_RESOURCE)) { | ||
1113 | unlock_task_sighand(task, &flags); | ||
1114 | put_task_struct(task); | ||
1115 | return -EACCES; | ||
1116 | } | ||
1117 | |||
1118 | task->signal->oom_score_adj = oom_score_adj; | ||
1119 | /* | ||
1120 | * Scale /proc/pid/oom_adj appropriately ensuring that OOM_DISABLE is | ||
1121 | * always attainable. | ||
1122 | */ | ||
1123 | if (task->signal->oom_score_adj == OOM_SCORE_ADJ_MIN) | ||
1124 | task->signal->oom_adj = OOM_DISABLE; | ||
1125 | else | ||
1126 | task->signal->oom_adj = (oom_score_adj * OOM_ADJUST_MAX) / | ||
1127 | OOM_SCORE_ADJ_MAX; | ||
1128 | unlock_task_sighand(task, &flags); | ||
1129 | put_task_struct(task); | ||
1130 | return count; | ||
1131 | } | ||
1132 | |||
1133 | static const struct file_operations proc_oom_score_adj_operations = { | ||
1134 | .read = oom_score_adj_read, | ||
1135 | .write = oom_score_adj_write, | ||
1136 | }; | ||
1137 | |||
1054 | #ifdef CONFIG_AUDITSYSCALL | 1138 | #ifdef CONFIG_AUDITSYSCALL |
1055 | #define TMPBUFLEN 21 | 1139 | #define TMPBUFLEN 21 |
1056 | static ssize_t proc_loginuid_read(struct file * file, char __user * buf, | 1140 | static ssize_t proc_loginuid_read(struct file * file, char __user * buf, |
@@ -2623,6 +2707,7 @@ static const struct pid_entry tgid_base_stuff[] = { | |||
2623 | #endif | 2707 | #endif |
2624 | INF("oom_score", S_IRUGO, proc_oom_score), | 2708 | INF("oom_score", S_IRUGO, proc_oom_score), |
2625 | REG("oom_adj", S_IRUGO|S_IWUSR, proc_oom_adjust_operations), | 2709 | REG("oom_adj", S_IRUGO|S_IWUSR, proc_oom_adjust_operations), |
2710 | REG("oom_score_adj", S_IRUGO|S_IWUSR, proc_oom_score_adj_operations), | ||
2626 | #ifdef CONFIG_AUDITSYSCALL | 2711 | #ifdef CONFIG_AUDITSYSCALL |
2627 | REG("loginuid", S_IWUSR|S_IRUGO, proc_loginuid_operations), | 2712 | REG("loginuid", S_IWUSR|S_IRUGO, proc_loginuid_operations), |
2628 | REG("sessionid", S_IRUGO, proc_sessionid_operations), | 2713 | REG("sessionid", S_IRUGO, proc_sessionid_operations), |
@@ -2957,6 +3042,7 @@ static const struct pid_entry tid_base_stuff[] = { | |||
2957 | #endif | 3042 | #endif |
2958 | INF("oom_score", S_IRUGO, proc_oom_score), | 3043 | INF("oom_score", S_IRUGO, proc_oom_score), |
2959 | REG("oom_adj", S_IRUGO|S_IWUSR, proc_oom_adjust_operations), | 3044 | REG("oom_adj", S_IRUGO|S_IWUSR, proc_oom_adjust_operations), |
3045 | REG("oom_score_adj", S_IRUGO|S_IWUSR, proc_oom_score_adj_operations), | ||
2960 | #ifdef CONFIG_AUDITSYSCALL | 3046 | #ifdef CONFIG_AUDITSYSCALL |
2961 | REG("loginuid", S_IWUSR|S_IRUGO, proc_loginuid_operations), | 3047 | REG("loginuid", S_IWUSR|S_IRUGO, proc_loginuid_operations), |
2962 | REG("sessionid", S_IRUSR, proc_sessionid_operations), | 3048 | REG("sessionid", S_IRUSR, proc_sessionid_operations), |