diff options
Diffstat (limited to 'fs/proc/base.c')
| -rw-r--r-- | fs/proc/base.c | 99 |
1 files changed, 72 insertions, 27 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c index dc5d5f51f3fe..53dc8ad40ae6 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
| @@ -1023,28 +1023,47 @@ static ssize_t oom_adjust_write(struct file *file, const char __user *buf, | |||
| 1023 | memset(buffer, 0, sizeof(buffer)); | 1023 | memset(buffer, 0, sizeof(buffer)); |
| 1024 | if (count > sizeof(buffer) - 1) | 1024 | if (count > sizeof(buffer) - 1) |
| 1025 | count = sizeof(buffer) - 1; | 1025 | count = sizeof(buffer) - 1; |
| 1026 | if (copy_from_user(buffer, buf, count)) | 1026 | if (copy_from_user(buffer, buf, count)) { |
| 1027 | return -EFAULT; | 1027 | err = -EFAULT; |
| 1028 | goto out; | ||
| 1029 | } | ||
| 1028 | 1030 | ||
| 1029 | err = strict_strtol(strstrip(buffer), 0, &oom_adjust); | 1031 | err = strict_strtol(strstrip(buffer), 0, &oom_adjust); |
| 1030 | if (err) | 1032 | if (err) |
| 1031 | return -EINVAL; | 1033 | goto out; |
| 1032 | if ((oom_adjust < OOM_ADJUST_MIN || oom_adjust > OOM_ADJUST_MAX) && | 1034 | if ((oom_adjust < OOM_ADJUST_MIN || oom_adjust > OOM_ADJUST_MAX) && |
| 1033 | oom_adjust != OOM_DISABLE) | 1035 | oom_adjust != OOM_DISABLE) { |
| 1034 | return -EINVAL; | 1036 | err = -EINVAL; |
| 1037 | goto out; | ||
| 1038 | } | ||
| 1035 | 1039 | ||
| 1036 | task = get_proc_task(file->f_path.dentry->d_inode); | 1040 | task = get_proc_task(file->f_path.dentry->d_inode); |
| 1037 | if (!task) | 1041 | if (!task) { |
| 1038 | return -ESRCH; | 1042 | err = -ESRCH; |
| 1043 | goto out; | ||
| 1044 | } | ||
| 1045 | |||
| 1046 | task_lock(task); | ||
| 1047 | if (!task->mm) { | ||
| 1048 | err = -EINVAL; | ||
| 1049 | goto err_task_lock; | ||
| 1050 | } | ||
| 1051 | |||
| 1039 | if (!lock_task_sighand(task, &flags)) { | 1052 | if (!lock_task_sighand(task, &flags)) { |
| 1040 | put_task_struct(task); | 1053 | err = -ESRCH; |
| 1041 | return -ESRCH; | 1054 | goto err_task_lock; |
| 1042 | } | 1055 | } |
| 1043 | 1056 | ||
| 1044 | if (oom_adjust < task->signal->oom_adj && !capable(CAP_SYS_RESOURCE)) { | 1057 | if (oom_adjust < task->signal->oom_adj && !capable(CAP_SYS_RESOURCE)) { |
| 1045 | unlock_task_sighand(task, &flags); | 1058 | err = -EACCES; |
| 1046 | put_task_struct(task); | 1059 | goto err_sighand; |
| 1047 | return -EACCES; | 1060 | } |
| 1061 | |||
| 1062 | if (oom_adjust != task->signal->oom_adj) { | ||
| 1063 | if (oom_adjust == OOM_DISABLE) | ||
| 1064 | atomic_inc(&task->mm->oom_disable_count); | ||
| 1065 | if (task->signal->oom_adj == OOM_DISABLE) | ||
| 1066 | atomic_dec(&task->mm->oom_disable_count); | ||
| 1048 | } | 1067 | } |
| 1049 | 1068 | ||
| 1050 | /* | 1069 | /* |
| @@ -1065,10 +1084,13 @@ static ssize_t oom_adjust_write(struct file *file, const char __user *buf, | |||
| 1065 | else | 1084 | else |
| 1066 | task->signal->oom_score_adj = (oom_adjust * OOM_SCORE_ADJ_MAX) / | 1085 | task->signal->oom_score_adj = (oom_adjust * OOM_SCORE_ADJ_MAX) / |
| 1067 | -OOM_DISABLE; | 1086 | -OOM_DISABLE; |
| 1087 | err_sighand: | ||
| 1068 | unlock_task_sighand(task, &flags); | 1088 | unlock_task_sighand(task, &flags); |
| 1089 | err_task_lock: | ||
| 1090 | task_unlock(task); | ||
| 1069 | put_task_struct(task); | 1091 | put_task_struct(task); |
| 1070 | 1092 | out: | |
| 1071 | return count; | 1093 | return err < 0 ? err : count; |
| 1072 | } | 1094 | } |
| 1073 | 1095 | ||
| 1074 | static const struct file_operations proc_oom_adjust_operations = { | 1096 | static const struct file_operations proc_oom_adjust_operations = { |
| @@ -1109,30 +1131,49 @@ static ssize_t oom_score_adj_write(struct file *file, const char __user *buf, | |||
| 1109 | memset(buffer, 0, sizeof(buffer)); | 1131 | memset(buffer, 0, sizeof(buffer)); |
| 1110 | if (count > sizeof(buffer) - 1) | 1132 | if (count > sizeof(buffer) - 1) |
| 1111 | count = sizeof(buffer) - 1; | 1133 | count = sizeof(buffer) - 1; |
| 1112 | if (copy_from_user(buffer, buf, count)) | 1134 | if (copy_from_user(buffer, buf, count)) { |
| 1113 | return -EFAULT; | 1135 | err = -EFAULT; |
| 1136 | goto out; | ||
| 1137 | } | ||
| 1114 | 1138 | ||
| 1115 | err = strict_strtol(strstrip(buffer), 0, &oom_score_adj); | 1139 | err = strict_strtol(strstrip(buffer), 0, &oom_score_adj); |
| 1116 | if (err) | 1140 | if (err) |
| 1117 | return -EINVAL; | 1141 | goto out; |
| 1118 | if (oom_score_adj < OOM_SCORE_ADJ_MIN || | 1142 | if (oom_score_adj < OOM_SCORE_ADJ_MIN || |
| 1119 | oom_score_adj > OOM_SCORE_ADJ_MAX) | 1143 | oom_score_adj > OOM_SCORE_ADJ_MAX) { |
| 1120 | return -EINVAL; | 1144 | err = -EINVAL; |
| 1145 | goto out; | ||
| 1146 | } | ||
| 1121 | 1147 | ||
| 1122 | task = get_proc_task(file->f_path.dentry->d_inode); | 1148 | task = get_proc_task(file->f_path.dentry->d_inode); |
| 1123 | if (!task) | 1149 | if (!task) { |
| 1124 | return -ESRCH; | 1150 | err = -ESRCH; |
| 1151 | goto out; | ||
| 1152 | } | ||
| 1153 | |||
| 1154 | task_lock(task); | ||
| 1155 | if (!task->mm) { | ||
| 1156 | err = -EINVAL; | ||
| 1157 | goto err_task_lock; | ||
| 1158 | } | ||
| 1159 | |||
| 1125 | if (!lock_task_sighand(task, &flags)) { | 1160 | if (!lock_task_sighand(task, &flags)) { |
| 1126 | put_task_struct(task); | 1161 | err = -ESRCH; |
| 1127 | return -ESRCH; | 1162 | goto err_task_lock; |
| 1128 | } | 1163 | } |
| 1164 | |||
| 1129 | if (oom_score_adj < task->signal->oom_score_adj && | 1165 | if (oom_score_adj < task->signal->oom_score_adj && |
| 1130 | !capable(CAP_SYS_RESOURCE)) { | 1166 | !capable(CAP_SYS_RESOURCE)) { |
| 1131 | unlock_task_sighand(task, &flags); | 1167 | err = -EACCES; |
| 1132 | put_task_struct(task); | 1168 | goto err_sighand; |
| 1133 | return -EACCES; | ||
| 1134 | } | 1169 | } |
| 1135 | 1170 | ||
| 1171 | if (oom_score_adj != task->signal->oom_score_adj) { | ||
| 1172 | if (oom_score_adj == OOM_SCORE_ADJ_MIN) | ||
| 1173 | atomic_inc(&task->mm->oom_disable_count); | ||
| 1174 | if (task->signal->oom_score_adj == OOM_SCORE_ADJ_MIN) | ||
| 1175 | atomic_dec(&task->mm->oom_disable_count); | ||
| 1176 | } | ||
| 1136 | task->signal->oom_score_adj = oom_score_adj; | 1177 | task->signal->oom_score_adj = oom_score_adj; |
| 1137 | /* | 1178 | /* |
| 1138 | * Scale /proc/pid/oom_adj appropriately ensuring that OOM_DISABLE is | 1179 | * Scale /proc/pid/oom_adj appropriately ensuring that OOM_DISABLE is |
| @@ -1143,9 +1184,13 @@ static ssize_t oom_score_adj_write(struct file *file, const char __user *buf, | |||
| 1143 | else | 1184 | else |
| 1144 | task->signal->oom_adj = (oom_score_adj * OOM_ADJUST_MAX) / | 1185 | task->signal->oom_adj = (oom_score_adj * OOM_ADJUST_MAX) / |
| 1145 | OOM_SCORE_ADJ_MAX; | 1186 | OOM_SCORE_ADJ_MAX; |
| 1187 | err_sighand: | ||
| 1146 | unlock_task_sighand(task, &flags); | 1188 | unlock_task_sighand(task, &flags); |
| 1189 | err_task_lock: | ||
| 1190 | task_unlock(task); | ||
| 1147 | put_task_struct(task); | 1191 | put_task_struct(task); |
| 1148 | return count; | 1192 | out: |
| 1193 | return err < 0 ? err : count; | ||
| 1149 | } | 1194 | } |
| 1150 | 1195 | ||
| 1151 | static const struct file_operations proc_oom_score_adj_operations = { | 1196 | static const struct file_operations proc_oom_score_adj_operations = { |
