diff options
| -rw-r--r-- | Documentation/filesystems/proc.txt | 16 | ||||
| -rw-r--r-- | fs/proc/base.c | 109 | ||||
| -rw-r--r-- | include/uapi/linux/oom.h | 9 |
3 files changed, 130 insertions, 4 deletions
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt index a1793d670cd0..3844d21d6ca3 100644 --- a/Documentation/filesystems/proc.txt +++ b/Documentation/filesystems/proc.txt | |||
| @@ -33,7 +33,7 @@ Table of Contents | |||
| 33 | 2 Modifying System Parameters | 33 | 2 Modifying System Parameters |
| 34 | 34 | ||
| 35 | 3 Per-Process Parameters | 35 | 3 Per-Process Parameters |
| 36 | 3.1 /proc/<pid>/oom_score_adj - Adjust the oom-killer | 36 | 3.1 /proc/<pid>/oom_adj & /proc/<pid>/oom_score_adj - Adjust the oom-killer |
| 37 | score | 37 | score |
| 38 | 3.2 /proc/<pid>/oom_score - Display current oom-killer score | 38 | 3.2 /proc/<pid>/oom_score - Display current oom-killer score |
| 39 | 3.3 /proc/<pid>/io - Display the IO accounting fields | 39 | 3.3 /proc/<pid>/io - Display the IO accounting fields |
| @@ -1320,10 +1320,10 @@ of the kernel. | |||
| 1320 | CHAPTER 3: PER-PROCESS PARAMETERS | 1320 | CHAPTER 3: PER-PROCESS PARAMETERS |
| 1321 | ------------------------------------------------------------------------------ | 1321 | ------------------------------------------------------------------------------ |
| 1322 | 1322 | ||
| 1323 | 3.1 /proc/<pid>/oom_score_adj- Adjust the oom-killer score | 1323 | 3.1 /proc/<pid>/oom_adj & /proc/<pid>/oom_score_adj- Adjust the oom-killer score |
| 1324 | -------------------------------------------------------------------------------- | 1324 | -------------------------------------------------------------------------------- |
| 1325 | 1325 | ||
| 1326 | This file can be used to adjust the badness heuristic used to select which | 1326 | These file can be used to adjust the badness heuristic used to select which |
| 1327 | process gets killed in out of memory conditions. | 1327 | process gets killed in out of memory conditions. |
| 1328 | 1328 | ||
| 1329 | The badness heuristic assigns a value to each candidate task ranging from 0 | 1329 | The badness heuristic assigns a value to each candidate task ranging from 0 |
| @@ -1361,6 +1361,12 @@ same system, cpuset, mempolicy, or memory controller resources to use at least | |||
| 1361 | equivalent to discounting 50% of the task's allowed memory from being considered | 1361 | equivalent to discounting 50% of the task's allowed memory from being considered |
| 1362 | as scoring against the task. | 1362 | as scoring against the task. |
| 1363 | 1363 | ||
| 1364 | For backwards compatibility with previous kernels, /proc/<pid>/oom_adj may also | ||
| 1365 | be used to tune the badness score. Its acceptable values range from -16 | ||
| 1366 | (OOM_ADJUST_MIN) to +15 (OOM_ADJUST_MAX) and a special value of -17 | ||
| 1367 | (OOM_DISABLE) to disable oom killing entirely for that task. Its value is | ||
| 1368 | scaled linearly with /proc/<pid>/oom_score_adj. | ||
| 1369 | |||
| 1364 | The value of /proc/<pid>/oom_score_adj may be reduced no lower than the last | 1370 | The value of /proc/<pid>/oom_score_adj may be reduced no lower than the last |
| 1365 | value set by a CAP_SYS_RESOURCE process. To reduce the value any lower | 1371 | value set by a CAP_SYS_RESOURCE process. To reduce the value any lower |
| 1366 | requires CAP_SYS_RESOURCE. | 1372 | requires CAP_SYS_RESOURCE. |
| @@ -1375,7 +1381,9 @@ minimal amount of work. | |||
| 1375 | ------------------------------------------------------------- | 1381 | ------------------------------------------------------------- |
| 1376 | 1382 | ||
| 1377 | This file can be used to check the current score used by the oom-killer is for | 1383 | This file can be used to check the current score used by the oom-killer is for |
| 1378 | any given <pid>. | 1384 | any given <pid>. Use it together with /proc/<pid>/oom_score_adj to tune which |
| 1385 | process should be killed in an out-of-memory situation. | ||
| 1386 | |||
| 1379 | 1387 | ||
| 1380 | 3.3 /proc/<pid>/io - Display the IO accounting fields | 1388 | 3.3 /proc/<pid>/io - Display the IO accounting fields |
| 1381 | ------------------------------------------------------- | 1389 | ------------------------------------------------------- |
diff --git a/fs/proc/base.c b/fs/proc/base.c index 144a96732dd7..3c231adf8450 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
| @@ -873,6 +873,113 @@ static const struct file_operations proc_environ_operations = { | |||
| 873 | .release = mem_release, | 873 | .release = mem_release, |
| 874 | }; | 874 | }; |
| 875 | 875 | ||
| 876 | static ssize_t oom_adj_read(struct file *file, char __user *buf, size_t count, | ||
| 877 | loff_t *ppos) | ||
| 878 | { | ||
| 879 | struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode); | ||
| 880 | char buffer[PROC_NUMBUF]; | ||
| 881 | int oom_adj = OOM_ADJUST_MIN; | ||
| 882 | size_t len; | ||
| 883 | unsigned long flags; | ||
| 884 | |||
| 885 | if (!task) | ||
| 886 | return -ESRCH; | ||
| 887 | if (lock_task_sighand(task, &flags)) { | ||
| 888 | if (task->signal->oom_score_adj == OOM_SCORE_ADJ_MAX) | ||
| 889 | oom_adj = OOM_ADJUST_MAX; | ||
| 890 | else | ||
| 891 | oom_adj = (task->signal->oom_score_adj * -OOM_DISABLE) / | ||
| 892 | OOM_SCORE_ADJ_MAX; | ||
| 893 | unlock_task_sighand(task, &flags); | ||
| 894 | } | ||
| 895 | put_task_struct(task); | ||
| 896 | len = snprintf(buffer, sizeof(buffer), "%d\n", oom_adj); | ||
| 897 | return simple_read_from_buffer(buf, count, ppos, buffer, len); | ||
| 898 | } | ||
| 899 | |||
| 900 | static ssize_t oom_adj_write(struct file *file, const char __user *buf, | ||
| 901 | size_t count, loff_t *ppos) | ||
| 902 | { | ||
| 903 | struct task_struct *task; | ||
| 904 | char buffer[PROC_NUMBUF]; | ||
| 905 | int oom_adj; | ||
| 906 | unsigned long flags; | ||
| 907 | int err; | ||
| 908 | |||
| 909 | memset(buffer, 0, sizeof(buffer)); | ||
| 910 | if (count > sizeof(buffer) - 1) | ||
| 911 | count = sizeof(buffer) - 1; | ||
| 912 | if (copy_from_user(buffer, buf, count)) { | ||
| 913 | err = -EFAULT; | ||
| 914 | goto out; | ||
| 915 | } | ||
| 916 | |||
| 917 | err = kstrtoint(strstrip(buffer), 0, &oom_adj); | ||
| 918 | if (err) | ||
| 919 | goto out; | ||
| 920 | if ((oom_adj < OOM_ADJUST_MIN || oom_adj > OOM_ADJUST_MAX) && | ||
| 921 | oom_adj != OOM_DISABLE) { | ||
| 922 | err = -EINVAL; | ||
| 923 | goto out; | ||
| 924 | } | ||
| 925 | |||
| 926 | task = get_proc_task(file->f_path.dentry->d_inode); | ||
| 927 | if (!task) { | ||
| 928 | err = -ESRCH; | ||
| 929 | goto out; | ||
| 930 | } | ||
| 931 | |||
| 932 | task_lock(task); | ||
| 933 | if (!task->mm) { | ||
| 934 | err = -EINVAL; | ||
| 935 | goto err_task_lock; | ||
| 936 | } | ||
| 937 | |||
| 938 | if (!lock_task_sighand(task, &flags)) { | ||
| 939 | err = -ESRCH; | ||
| 940 | goto err_task_lock; | ||
| 941 | } | ||
| 942 | |||
| 943 | /* | ||
| 944 | * Scale /proc/pid/oom_score_adj appropriately ensuring that a maximum | ||
| 945 | * value is always attainable. | ||
| 946 | */ | ||
| 947 | if (oom_adj == OOM_ADJUST_MAX) | ||
| 948 | oom_adj = OOM_SCORE_ADJ_MAX; | ||
| 949 | else | ||
| 950 | oom_adj = (oom_adj * OOM_SCORE_ADJ_MAX) / -OOM_DISABLE; | ||
| 951 | |||
| 952 | if (oom_adj < task->signal->oom_score_adj && | ||
| 953 | !capable(CAP_SYS_RESOURCE)) { | ||
| 954 | err = -EACCES; | ||
| 955 | goto err_sighand; | ||
| 956 | } | ||
| 957 | |||
| 958 | /* | ||
| 959 | * /proc/pid/oom_adj is provided for legacy purposes, ask users to use | ||
| 960 | * /proc/pid/oom_score_adj instead. | ||
| 961 | */ | ||
| 962 | printk_once(KERN_WARNING "%s (%d): /proc/%d/oom_adj is deprecated, please use /proc/%d/oom_score_adj instead.\n", | ||
| 963 | current->comm, task_pid_nr(current), task_pid_nr(task), | ||
| 964 | task_pid_nr(task)); | ||
| 965 | |||
| 966 | task->signal->oom_score_adj = oom_adj; | ||
| 967 | trace_oom_score_adj_update(task); | ||
| 968 | err_sighand: | ||
| 969 | unlock_task_sighand(task, &flags); | ||
| 970 | err_task_lock: | ||
| 971 | task_unlock(task); | ||
| 972 | put_task_struct(task); | ||
| 973 | out: | ||
| 974 | return err < 0 ? err : count; | ||
| 975 | } | ||
| 976 | |||
| 977 | static const struct file_operations proc_oom_adj_operations = { | ||
| 978 | .read = oom_adj_read, | ||
| 979 | .write = oom_adj_write, | ||
| 980 | .llseek = generic_file_llseek, | ||
| 981 | }; | ||
| 982 | |||
| 876 | static ssize_t oom_score_adj_read(struct file *file, char __user *buf, | 983 | static ssize_t oom_score_adj_read(struct file *file, char __user *buf, |
| 877 | size_t count, loff_t *ppos) | 984 | size_t count, loff_t *ppos) |
| 878 | { | 985 | { |
| @@ -2598,6 +2705,7 @@ static const struct pid_entry tgid_base_stuff[] = { | |||
| 2598 | REG("cgroup", S_IRUGO, proc_cgroup_operations), | 2705 | REG("cgroup", S_IRUGO, proc_cgroup_operations), |
| 2599 | #endif | 2706 | #endif |
| 2600 | INF("oom_score", S_IRUGO, proc_oom_score), | 2707 | INF("oom_score", S_IRUGO, proc_oom_score), |
| 2708 | REG("oom_adj", S_IRUGO|S_IWUSR, proc_oom_adj_operations), | ||
| 2601 | REG("oom_score_adj", S_IRUGO|S_IWUSR, proc_oom_score_adj_operations), | 2709 | REG("oom_score_adj", S_IRUGO|S_IWUSR, proc_oom_score_adj_operations), |
| 2602 | #ifdef CONFIG_AUDITSYSCALL | 2710 | #ifdef CONFIG_AUDITSYSCALL |
| 2603 | REG("loginuid", S_IWUSR|S_IRUGO, proc_loginuid_operations), | 2711 | REG("loginuid", S_IWUSR|S_IRUGO, proc_loginuid_operations), |
| @@ -2964,6 +3072,7 @@ static const struct pid_entry tid_base_stuff[] = { | |||
| 2964 | REG("cgroup", S_IRUGO, proc_cgroup_operations), | 3072 | REG("cgroup", S_IRUGO, proc_cgroup_operations), |
| 2965 | #endif | 3073 | #endif |
| 2966 | INF("oom_score", S_IRUGO, proc_oom_score), | 3074 | INF("oom_score", S_IRUGO, proc_oom_score), |
| 3075 | REG("oom_adj", S_IRUGO|S_IWUSR, proc_oom_adj_operations), | ||
| 2967 | REG("oom_score_adj", S_IRUGO|S_IWUSR, proc_oom_score_adj_operations), | 3076 | REG("oom_score_adj", S_IRUGO|S_IWUSR, proc_oom_score_adj_operations), |
| 2968 | #ifdef CONFIG_AUDITSYSCALL | 3077 | #ifdef CONFIG_AUDITSYSCALL |
| 2969 | REG("loginuid", S_IWUSR|S_IRUGO, proc_loginuid_operations), | 3078 | REG("loginuid", S_IWUSR|S_IRUGO, proc_loginuid_operations), |
diff --git a/include/uapi/linux/oom.h b/include/uapi/linux/oom.h index a49c4afc7060..b29272d621ce 100644 --- a/include/uapi/linux/oom.h +++ b/include/uapi/linux/oom.h | |||
| @@ -8,4 +8,13 @@ | |||
| 8 | #define OOM_SCORE_ADJ_MIN (-1000) | 8 | #define OOM_SCORE_ADJ_MIN (-1000) |
| 9 | #define OOM_SCORE_ADJ_MAX 1000 | 9 | #define OOM_SCORE_ADJ_MAX 1000 |
| 10 | 10 | ||
| 11 | /* | ||
| 12 | * /proc/<pid>/oom_adj set to -17 protects from the oom killer for legacy | ||
| 13 | * purposes. | ||
| 14 | */ | ||
| 15 | #define OOM_DISABLE (-17) | ||
| 16 | /* inclusive */ | ||
| 17 | #define OOM_ADJUST_MIN (-16) | ||
| 18 | #define OOM_ADJUST_MAX 15 | ||
| 19 | |||
| 11 | #endif /* _UAPI__INCLUDE_LINUX_OOM_H */ | 20 | #endif /* _UAPI__INCLUDE_LINUX_OOM_H */ |
