diff options
author | David Rientjes <rientjes@google.com> | 2012-11-12 20:53:04 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-11-16 13:15:35 -0500 |
commit | fa0cbbf145aabbf29c6f28f8a11935c0b0fd86fc (patch) | |
tree | fd2626b68b0f78afa128d7772c49f066e339bd3a /fs/proc/base.c | |
parent | f4bcd79c88d25508643084e6fed25920485db0eb (diff) |
mm, oom: reintroduce /proc/pid/oom_adj
This is mostly a revert of 01dc52ebdf47 ("oom: remove deprecated oom_adj")
from Davidlohr Bueso.
It reintroduces /proc/pid/oom_adj for backwards compatibility with earlier
kernels. It simply scales the value linearly when /proc/pid/oom_score_adj
is written.
The major difference is that its scheduled removal is no longer included
in Documentation/feature-removal-schedule.txt. We do warn users with a
single printk, though, to suggest the more powerful and supported
/proc/pid/oom_score_adj interface.
Reported-by: Artem S. Tashkinov <t.artem@lycos.com>
Signed-off-by: David Rientjes <rientjes@google.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/proc/base.c')
-rw-r--r-- | fs/proc/base.c | 109 |
1 files changed, 109 insertions, 0 deletions
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), |