diff options
author | Michal Hocko <mhocko@suse.com> | 2016-07-28 18:44:37 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-07-28 19:07:41 -0400 |
commit | f913da596a407d3be7c8c220697beacd8fe7312a (patch) | |
tree | fc11a3aadb00474f956f6c449a7a6a1d0e0776f8 /fs/proc/base.c | |
parent | d49fbf766d27bc721caa48b391103d71e90804fa (diff) |
proc, oom: drop bogus sighand lock
Oleg has pointed out that can simplify both oom_adj_{read,write} and
oom_score_adj_{read,write} even further and drop the sighand lock. The
main purpose of the lock was to protect p->signal from going away but this
will not happen since ea6d290ca34c ("signals: make task_struct->signal
immutable/refcountable").
The other role of the lock was to synchronize different writers,
especially those with CAP_SYS_RESOURCE. Introduce a mutex for this
purpose. Later patches will need this lock anyway.
Suggested-by: Oleg Nesterov <oleg@redhat.com>
Link: http://lkml.kernel.org/r/1466426628-15074-3-git-send-email-mhocko@kernel.org
Signed-off-by: Michal Hocko <mhocko@suse.com>
Acked-by: Oleg Nesterov <oleg@redhat.com>
Cc: Vladimir Davydov <vdavydov@virtuozzo.com>
Cc: David Rientjes <rientjes@google.com>
Cc: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/proc/base.c')
-rw-r--r-- | fs/proc/base.c | 51 |
1 files changed, 17 insertions, 34 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c index 2a0f5ee9b623..f7dc1050387f 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -1024,23 +1024,21 @@ static ssize_t oom_adj_read(struct file *file, char __user *buf, size_t count, | |||
1024 | char buffer[PROC_NUMBUF]; | 1024 | char buffer[PROC_NUMBUF]; |
1025 | int oom_adj = OOM_ADJUST_MIN; | 1025 | int oom_adj = OOM_ADJUST_MIN; |
1026 | size_t len; | 1026 | size_t len; |
1027 | unsigned long flags; | ||
1028 | 1027 | ||
1029 | if (!task) | 1028 | if (!task) |
1030 | return -ESRCH; | 1029 | return -ESRCH; |
1031 | if (lock_task_sighand(task, &flags)) { | 1030 | if (task->signal->oom_score_adj == OOM_SCORE_ADJ_MAX) |
1032 | if (task->signal->oom_score_adj == OOM_SCORE_ADJ_MAX) | 1031 | oom_adj = OOM_ADJUST_MAX; |
1033 | oom_adj = OOM_ADJUST_MAX; | 1032 | else |
1034 | else | 1033 | oom_adj = (task->signal->oom_score_adj * -OOM_DISABLE) / |
1035 | oom_adj = (task->signal->oom_score_adj * -OOM_DISABLE) / | 1034 | OOM_SCORE_ADJ_MAX; |
1036 | OOM_SCORE_ADJ_MAX; | ||
1037 | unlock_task_sighand(task, &flags); | ||
1038 | } | ||
1039 | put_task_struct(task); | 1035 | put_task_struct(task); |
1040 | len = snprintf(buffer, sizeof(buffer), "%d\n", oom_adj); | 1036 | len = snprintf(buffer, sizeof(buffer), "%d\n", oom_adj); |
1041 | return simple_read_from_buffer(buf, count, ppos, buffer, len); | 1037 | return simple_read_from_buffer(buf, count, ppos, buffer, len); |
1042 | } | 1038 | } |
1043 | 1039 | ||
1040 | static DEFINE_MUTEX(oom_adj_mutex); | ||
1041 | |||
1044 | /* | 1042 | /* |
1045 | * /proc/pid/oom_adj exists solely for backwards compatibility with previous | 1043 | * /proc/pid/oom_adj exists solely for backwards compatibility with previous |
1046 | * kernels. The effective policy is defined by oom_score_adj, which has a | 1044 | * kernels. The effective policy is defined by oom_score_adj, which has a |
@@ -1057,7 +1055,6 @@ static ssize_t oom_adj_write(struct file *file, const char __user *buf, | |||
1057 | struct task_struct *task; | 1055 | struct task_struct *task; |
1058 | char buffer[PROC_NUMBUF]; | 1056 | char buffer[PROC_NUMBUF]; |
1059 | int oom_adj; | 1057 | int oom_adj; |
1060 | unsigned long flags; | ||
1061 | int err; | 1058 | int err; |
1062 | 1059 | ||
1063 | memset(buffer, 0, sizeof(buffer)); | 1060 | memset(buffer, 0, sizeof(buffer)); |
@@ -1083,11 +1080,6 @@ static ssize_t oom_adj_write(struct file *file, const char __user *buf, | |||
1083 | goto out; | 1080 | goto out; |
1084 | } | 1081 | } |
1085 | 1082 | ||
1086 | if (!lock_task_sighand(task, &flags)) { | ||
1087 | err = -ESRCH; | ||
1088 | goto err_put_task; | ||
1089 | } | ||
1090 | |||
1091 | /* | 1083 | /* |
1092 | * Scale /proc/pid/oom_score_adj appropriately ensuring that a maximum | 1084 | * Scale /proc/pid/oom_score_adj appropriately ensuring that a maximum |
1093 | * value is always attainable. | 1085 | * value is always attainable. |
@@ -1097,10 +1089,11 @@ static ssize_t oom_adj_write(struct file *file, const char __user *buf, | |||
1097 | else | 1089 | else |
1098 | oom_adj = (oom_adj * OOM_SCORE_ADJ_MAX) / -OOM_DISABLE; | 1090 | oom_adj = (oom_adj * OOM_SCORE_ADJ_MAX) / -OOM_DISABLE; |
1099 | 1091 | ||
1092 | mutex_lock(&oom_adj_mutex); | ||
1100 | if (oom_adj < task->signal->oom_score_adj && | 1093 | if (oom_adj < task->signal->oom_score_adj && |
1101 | !capable(CAP_SYS_RESOURCE)) { | 1094 | !capable(CAP_SYS_RESOURCE)) { |
1102 | err = -EACCES; | 1095 | err = -EACCES; |
1103 | goto err_sighand; | 1096 | goto err_unlock; |
1104 | } | 1097 | } |
1105 | 1098 | ||
1106 | /* | 1099 | /* |
@@ -1113,9 +1106,8 @@ static ssize_t oom_adj_write(struct file *file, const char __user *buf, | |||
1113 | 1106 | ||
1114 | task->signal->oom_score_adj = oom_adj; | 1107 | task->signal->oom_score_adj = oom_adj; |
1115 | trace_oom_score_adj_update(task); | 1108 | trace_oom_score_adj_update(task); |
1116 | err_sighand: | 1109 | err_unlock: |
1117 | unlock_task_sighand(task, &flags); | 1110 | mutex_unlock(&oom_adj_mutex); |
1118 | err_put_task: | ||
1119 | put_task_struct(task); | 1111 | put_task_struct(task); |
1120 | out: | 1112 | out: |
1121 | return err < 0 ? err : count; | 1113 | return err < 0 ? err : count; |
@@ -1133,15 +1125,11 @@ static ssize_t oom_score_adj_read(struct file *file, char __user *buf, | |||
1133 | struct task_struct *task = get_proc_task(file_inode(file)); | 1125 | struct task_struct *task = get_proc_task(file_inode(file)); |
1134 | char buffer[PROC_NUMBUF]; | 1126 | char buffer[PROC_NUMBUF]; |
1135 | short oom_score_adj = OOM_SCORE_ADJ_MIN; | 1127 | short oom_score_adj = OOM_SCORE_ADJ_MIN; |
1136 | unsigned long flags; | ||
1137 | size_t len; | 1128 | size_t len; |
1138 | 1129 | ||
1139 | if (!task) | 1130 | if (!task) |
1140 | return -ESRCH; | 1131 | return -ESRCH; |
1141 | if (lock_task_sighand(task, &flags)) { | 1132 | oom_score_adj = task->signal->oom_score_adj; |
1142 | oom_score_adj = task->signal->oom_score_adj; | ||
1143 | unlock_task_sighand(task, &flags); | ||
1144 | } | ||
1145 | put_task_struct(task); | 1133 | put_task_struct(task); |
1146 | len = snprintf(buffer, sizeof(buffer), "%hd\n", oom_score_adj); | 1134 | len = snprintf(buffer, sizeof(buffer), "%hd\n", oom_score_adj); |
1147 | return simple_read_from_buffer(buf, count, ppos, buffer, len); | 1135 | return simple_read_from_buffer(buf, count, ppos, buffer, len); |
@@ -1152,7 +1140,6 @@ static ssize_t oom_score_adj_write(struct file *file, const char __user *buf, | |||
1152 | { | 1140 | { |
1153 | struct task_struct *task; | 1141 | struct task_struct *task; |
1154 | char buffer[PROC_NUMBUF]; | 1142 | char buffer[PROC_NUMBUF]; |
1155 | unsigned long flags; | ||
1156 | int oom_score_adj; | 1143 | int oom_score_adj; |
1157 | int err; | 1144 | int err; |
1158 | 1145 | ||
@@ -1179,25 +1166,21 @@ static ssize_t oom_score_adj_write(struct file *file, const char __user *buf, | |||
1179 | goto out; | 1166 | goto out; |
1180 | } | 1167 | } |
1181 | 1168 | ||
1182 | if (!lock_task_sighand(task, &flags)) { | 1169 | mutex_lock(&oom_adj_mutex); |
1183 | err = -ESRCH; | ||
1184 | goto err_put_task; | ||
1185 | } | ||
1186 | |||
1187 | if ((short)oom_score_adj < task->signal->oom_score_adj_min && | 1170 | if ((short)oom_score_adj < task->signal->oom_score_adj_min && |
1188 | !capable(CAP_SYS_RESOURCE)) { | 1171 | !capable(CAP_SYS_RESOURCE)) { |
1189 | err = -EACCES; | 1172 | err = -EACCES; |
1190 | goto err_sighand; | 1173 | goto err_unlock; |
1191 | } | 1174 | } |
1192 | 1175 | ||
1193 | task->signal->oom_score_adj = (short)oom_score_adj; | 1176 | task->signal->oom_score_adj = (short)oom_score_adj; |
1194 | if (has_capability_noaudit(current, CAP_SYS_RESOURCE)) | 1177 | if (has_capability_noaudit(current, CAP_SYS_RESOURCE)) |
1195 | task->signal->oom_score_adj_min = (short)oom_score_adj; | 1178 | task->signal->oom_score_adj_min = (short)oom_score_adj; |
1179 | |||
1196 | trace_oom_score_adj_update(task); | 1180 | trace_oom_score_adj_update(task); |
1197 | 1181 | ||
1198 | err_sighand: | 1182 | err_unlock: |
1199 | unlock_task_sighand(task, &flags); | 1183 | mutex_unlock(&oom_adj_mutex); |
1200 | err_put_task: | ||
1201 | put_task_struct(task); | 1184 | put_task_struct(task); |
1202 | out: | 1185 | out: |
1203 | return err < 0 ? err : count; | 1186 | return err < 0 ? err : count; |