Merge lp:~mad-wol/upstart/oom-score-stanza into lp:upstart
- oom-score-stanza
- Merge into trunk
Proposed by
Marc - A. Dahlhaus
Status: | Merged |
---|---|
Merged at revision: | 1281 |
Proposed branch: | lp:~mad-wol/upstart/oom-score-stanza |
Merge into: | lp:upstart |
Diff against target: |
554 lines (+337/-25) 8 files modified
init/errors.h (+2/-1) init/job_class.c (+1/-1) init/job_class.h (+4/-2) init/job_process.c (+11/-5) init/man/init.5 (+3/-3) init/parse_job.c (+30/-4) init/tests/test_job_class.c (+1/-1) init/tests/test_parse_job.c (+285/-8) |
To merge this branch: | bzr merge lp:~mad-wol/upstart/oom-score-stanza |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Scott James Remnant | Pending | ||
Review via email: mp+60037@code.launchpad.net |
Commit message
Description of the change
This adds support for the oom_score_adj procfs api.
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'init/errors.h' |
2 | --- init/errors.h 2009-06-23 09:29:35 +0000 |
3 | +++ init/errors.h 2011-05-05 10:18:25 +0000 |
4 | @@ -62,7 +62,8 @@ |
5 | #define PARSE_ILLEGAL_EXIT_STR N_("Illegal exit status, expected integer") |
6 | #define PARSE_ILLEGAL_UMASK_STR N_("Illegal file creation mask, expected octal integer") |
7 | #define PARSE_ILLEGAL_NICE_STR N_("Illegal nice value, expected -20 to 19") |
8 | -#define PARSE_ILLEGAL_OOM_STR N_("Illegal oom adjustment, expected -16 to 15 or never") |
9 | +#define PARSE_ILLEGAL_OOM_STR N_("Illegal oom adjustment, expected -16 to 15 or 'never'") |
10 | +#define PARSE_ILLEGAL_OOM_SCORE_STR N_("Illegal oom score adjustment, expected -999 to 1000 or 'never'") |
11 | #define PARSE_ILLEGAL_LIMIT_STR N_("Illegal limit, expected 'unlimited' or integer") |
12 | #define PARSE_EXPECTED_EVENT_STR N_("Expected event") |
13 | #define PARSE_EXPECTED_OPERATOR_STR N_("Expected operator") |
14 | |
15 | === modified file 'init/job_class.c' |
16 | --- init/job_class.c 2010-12-14 15:30:06 +0000 |
17 | +++ init/job_class.c 2011-05-05 10:18:25 +0000 |
18 | @@ -211,7 +211,7 @@ |
19 | |
20 | class->umask = JOB_DEFAULT_UMASK; |
21 | class->nice = 0; |
22 | - class->oom_adj = 0; |
23 | + class->oom_score_adj = 0; |
24 | |
25 | for (i = 0; i < RLIMIT_NLIMITS; i++) |
26 | class->limits[i] = NULL; |
27 | |
28 | === modified file 'init/job_class.h' |
29 | --- init/job_class.h 2010-12-14 15:30:06 +0000 |
30 | +++ init/job_class.h 2011-05-05 10:18:25 +0000 |
31 | @@ -93,7 +93,7 @@ |
32 | * @console: how to arrange processes' stdin/out/err file descriptors, |
33 | * @umask: file mode creation mask, |
34 | * @nice: process priority, |
35 | - * @oom_adj: OOM killer adjustment, |
36 | + * @oom_score_adj: OOM killer score adjustment, |
37 | * @limits: resource limits indexed by resource, |
38 | * @chroot: root directory of process (implies @chdir if not set), |
39 | * @chdir: working directory of process, |
40 | @@ -141,7 +141,7 @@ |
41 | |
42 | mode_t umask; |
43 | int nice; |
44 | - int oom_adj; |
45 | + int oom_score_adj; |
46 | struct rlimit *limits[RLIMIT_NLIMITS]; |
47 | char *chroot; |
48 | char *chdir; |
49 | @@ -150,6 +150,8 @@ |
50 | int debug; |
51 | } JobClass; |
52 | |
53 | +#define SCORE_TO_ADJ(x) ((x * ((x < 0) ? 17 : 15)) / 1000) |
54 | +#define ADJ_TO_SCORE(x) ((x * 1000) / ((x < 0) ? 17 : 15)) |
55 | |
56 | NIH_BEGIN_EXTERN |
57 | |
58 | |
59 | === modified file 'init/job_process.c' |
60 | --- init/job_process.c 2011-03-22 17:46:46 +0000 |
61 | +++ init/job_process.c 2011-05-05 10:18:25 +0000 |
62 | @@ -371,7 +371,7 @@ |
63 | { |
64 | sigset_t child_set, orig_set; |
65 | pid_t pid; |
66 | - int i, fds[2]; |
67 | + int i, fds[2], oom_value; |
68 | char filename[PATH_MAX]; |
69 | FILE *fd; |
70 | |
71 | @@ -493,16 +493,22 @@ |
72 | |
73 | /* Adjust the process OOM killer priority. |
74 | */ |
75 | - if (class->oom_adj) { |
76 | + if (class->oom_score_adj) { |
77 | snprintf (filename, sizeof (filename), |
78 | - "/proc/%d/oom_adj", getpid ()); |
79 | - |
80 | + "/proc/%d/oom_score_adj", getpid ()); |
81 | + oom_value = class->oom_score_adj; |
82 | fd = fopen (filename, "w"); |
83 | + if ((! fd) && (errno == EACCES)) { |
84 | + snprintf (filename, sizeof (filename), |
85 | + "/proc/%d/oom_adj", getpid ()); |
86 | + oom_value = SCORE_TO_ADJ(class->oom_score_adj); |
87 | + fd = fopen (filename, "w"); |
88 | + } |
89 | if (! fd) { |
90 | nih_error_raise_system (); |
91 | job_process_error_abort (fds[1], JOB_PROCESS_ERROR_OOM_ADJ, 0); |
92 | } else { |
93 | - fprintf (fd, "%d\n", class->oom_adj); |
94 | + fprintf (fd, "%d\n", oom_value); |
95 | |
96 | if (fclose (fd)) { |
97 | nih_error_raise_system (); |
98 | |
99 | === modified file 'init/man/init.5' |
100 | --- init/man/init.5 2011-03-15 18:36:57 +0000 |
101 | +++ init/man/init.5 2011-05-05 10:18:25 +0000 |
102 | @@ -500,15 +500,15 @@ |
103 | for more details. |
104 | .\" |
105 | .TP |
106 | -.B oom \fIADJUSTMENT\fR|\fBnever |
107 | +.B oom score \fIADJUSTMENT\fR|\fBnever |
108 | Normally the OOM killer regards all processes equally, this stanza |
109 | advises the kernel to treat this job differently. |
110 | |
111 | .I ADJUSTMENT |
112 | may be an integer value from |
113 | -.I -16 |
114 | +.I -999 |
115 | (very unlikely to be killed by the OOM killer) up to |
116 | -.I 14 |
117 | +.I 1000 |
118 | (very likely to be killed by the OOM killer). It may also be the special |
119 | value |
120 | .B never |
121 | |
122 | === modified file 'init/parse_job.c' |
123 | --- init/parse_job.c 2011-01-17 16:37:54 +0000 |
124 | +++ init/parse_job.c 2011-05-05 10:18:25 +0000 |
125 | @@ -2233,6 +2233,7 @@ |
126 | nih_local char *arg = NULL; |
127 | char *endptr; |
128 | size_t a_pos, a_lineno; |
129 | + int oom_adj; |
130 | int ret = -1; |
131 | |
132 | nih_assert (class != NULL); |
133 | @@ -2247,12 +2248,37 @@ |
134 | if (! arg) |
135 | goto finish; |
136 | |
137 | - if (! strcmp (arg, "never")) { |
138 | - class->oom_adj = -17; |
139 | + if (! strcmp (arg, "score")) { |
140 | + nih_local char *scorearg = NULL; |
141 | + |
142 | + /* Update error position to the score value */ |
143 | + *pos = a_pos; |
144 | + if (lineno) |
145 | + *lineno = a_lineno; |
146 | + |
147 | + scorearg = nih_config_next_arg (NULL, file, len, |
148 | + &a_pos, &a_lineno); |
149 | + if (! scorearg) |
150 | + goto finish; |
151 | + |
152 | + if (! strcmp (scorearg, "never")) { |
153 | + class->oom_score_adj = -1000; |
154 | + } else { |
155 | + errno = 0; |
156 | + class->oom_score_adj = (int)strtol (scorearg, &endptr, 10); |
157 | + if (errno || *endptr || |
158 | + (class->oom_score_adj < -1000) || |
159 | + (class->oom_score_adj > 1000)) |
160 | + nih_return_error (-1, PARSE_ILLEGAL_OOM, |
161 | + _(PARSE_ILLEGAL_OOM_SCORE_STR)); |
162 | + } |
163 | + } else if (! strcmp (arg, "never")) { |
164 | + class->oom_score_adj = -1000; |
165 | } else { |
166 | errno = 0; |
167 | - class->oom_adj = (int)strtol (arg, &endptr, 10); |
168 | - if (errno || *endptr || (class->oom_adj < -17) || (class->oom_adj > 15)) |
169 | + oom_adj = (int)strtol (arg, &endptr, 10); |
170 | + class->oom_score_adj = ADJ_TO_SCORE(oom_adj); |
171 | + if (errno || *endptr || (oom_adj < -17) || (oom_adj > 15)) |
172 | nih_return_error (-1, PARSE_ILLEGAL_OOM, |
173 | _(PARSE_ILLEGAL_OOM_STR)); |
174 | } |
175 | |
176 | === modified file 'init/tests/test_job_class.c' |
177 | --- init/tests/test_job_class.c 2011-03-16 22:42:48 +0000 |
178 | +++ init/tests/test_job_class.c 2011-05-05 10:18:25 +0000 |
179 | @@ -133,7 +133,7 @@ |
180 | |
181 | TEST_EQ (class->umask, 022); |
182 | TEST_EQ (class->nice, 0); |
183 | - TEST_EQ (class->oom_adj, 0); |
184 | + TEST_EQ (class->oom_score_adj, 0); |
185 | |
186 | for (i = 0; i < RLIMIT_NLIMITS; i++) |
187 | TEST_EQ_P (class->limits[i], NULL); |
188 | |
189 | === modified file 'init/tests/test_parse_job.c' |
190 | --- init/tests/test_parse_job.c 2010-12-14 16:20:38 +0000 |
191 | +++ init/tests/test_parse_job.c 2011-05-05 10:18:25 +0000 |
192 | @@ -6198,11 +6198,39 @@ |
193 | |
194 | TEST_ALLOC_SIZE (job, sizeof (JobClass)); |
195 | |
196 | - TEST_EQ (job->oom_adj, 10); |
197 | - |
198 | - nih_free (job); |
199 | - } |
200 | - |
201 | + TEST_EQ (job->oom_score_adj, ADJ_TO_SCORE(10)); |
202 | + |
203 | + nih_free (job); |
204 | + } |
205 | + |
206 | + TEST_FEATURE ("with positive score argument"); |
207 | + strcpy (buf, "oom score 100\n"); |
208 | + |
209 | + TEST_ALLOC_FAIL { |
210 | + pos = 0; |
211 | + lineno = 1; |
212 | + job = parse_job (NULL, "test", buf, strlen (buf), |
213 | + &pos, &lineno); |
214 | + |
215 | + if (test_alloc_failed) { |
216 | + TEST_EQ_P (job, NULL); |
217 | + |
218 | + err = nih_error_get (); |
219 | + TEST_EQ (err->number, ENOMEM); |
220 | + nih_free (err); |
221 | + |
222 | + continue; |
223 | + } |
224 | + |
225 | + TEST_EQ (pos, strlen (buf)); |
226 | + TEST_EQ (lineno, 2); |
227 | + |
228 | + TEST_ALLOC_SIZE (job, sizeof (JobClass)); |
229 | + |
230 | + TEST_EQ (job->oom_score_adj, 100); |
231 | + |
232 | + nih_free (job); |
233 | + } |
234 | |
235 | /* Check that an oom stanza with a negative timeout results |
236 | * in it being stored in the job. |
237 | @@ -6231,7 +6259,36 @@ |
238 | |
239 | TEST_ALLOC_SIZE (job, sizeof (JobClass)); |
240 | |
241 | - TEST_EQ (job->oom_adj, -10); |
242 | + TEST_EQ (job->oom_score_adj, ADJ_TO_SCORE(-10)); |
243 | + |
244 | + nih_free (job); |
245 | + } |
246 | + |
247 | + TEST_FEATURE ("with negative score argument"); |
248 | + strcpy (buf, "oom score -100\n"); |
249 | + |
250 | + TEST_ALLOC_FAIL { |
251 | + pos = 0; |
252 | + lineno = 1; |
253 | + job = parse_job (NULL, "test", buf, strlen (buf), |
254 | + &pos, &lineno); |
255 | + |
256 | + if (test_alloc_failed) { |
257 | + TEST_EQ_P (job, NULL); |
258 | + |
259 | + err = nih_error_get (); |
260 | + TEST_EQ (err->number, ENOMEM); |
261 | + nih_free (err); |
262 | + |
263 | + continue; |
264 | + } |
265 | + |
266 | + TEST_EQ (pos, strlen (buf)); |
267 | + TEST_EQ (lineno, 2); |
268 | + |
269 | + TEST_ALLOC_SIZE (job, sizeof (JobClass)); |
270 | + |
271 | + TEST_EQ (job->oom_score_adj, -100); |
272 | |
273 | nih_free (job); |
274 | } |
275 | @@ -6264,7 +6321,40 @@ |
276 | |
277 | TEST_ALLOC_SIZE (job, sizeof (JobClass)); |
278 | |
279 | - TEST_EQ (job->oom_adj, -17); |
280 | + TEST_EQ (job->oom_score_adj, ADJ_TO_SCORE(-17)); |
281 | + |
282 | + nih_free (job); |
283 | + } |
284 | + |
285 | + |
286 | + /* Check that an oom score stanza may have the special never |
287 | + * argument which stores -1000 in the job. |
288 | + */ |
289 | + TEST_FEATURE ("with never score argument"); |
290 | + strcpy (buf, "oom score never\n"); |
291 | + |
292 | + TEST_ALLOC_FAIL { |
293 | + pos = 0; |
294 | + lineno = 1; |
295 | + job = parse_job (NULL, "test", buf, strlen (buf), |
296 | + &pos, &lineno); |
297 | + |
298 | + if (test_alloc_failed) { |
299 | + TEST_EQ_P (job, NULL); |
300 | + |
301 | + err = nih_error_get (); |
302 | + TEST_EQ (err->number, ENOMEM); |
303 | + nih_free (err); |
304 | + |
305 | + continue; |
306 | + } |
307 | + |
308 | + TEST_EQ (pos, strlen (buf)); |
309 | + TEST_EQ (lineno, 2); |
310 | + |
311 | + TEST_ALLOC_SIZE (job, sizeof (JobClass)); |
312 | + |
313 | + TEST_EQ (job->oom_score_adj, -1000); |
314 | |
315 | nih_free (job); |
316 | } |
317 | @@ -6297,7 +6387,100 @@ |
318 | |
319 | TEST_ALLOC_SIZE (job, sizeof (JobClass)); |
320 | |
321 | - TEST_EQ (job->oom_adj, 10); |
322 | + TEST_EQ (job->oom_score_adj, ADJ_TO_SCORE(10)); |
323 | + |
324 | + nih_free (job); |
325 | + } |
326 | + |
327 | + TEST_FEATURE ("with multiple score stanzas"); |
328 | + strcpy (buf, "oom score -500\n"); |
329 | + strcat (buf, "oom score 500\n"); |
330 | + |
331 | + TEST_ALLOC_FAIL { |
332 | + pos = 0; |
333 | + lineno = 1; |
334 | + job = parse_job (NULL, "test", buf, strlen (buf), |
335 | + &pos, &lineno); |
336 | + |
337 | + if (test_alloc_failed) { |
338 | + TEST_EQ_P (job, NULL); |
339 | + |
340 | + err = nih_error_get (); |
341 | + TEST_EQ (err->number, ENOMEM); |
342 | + nih_free (err); |
343 | + |
344 | + continue; |
345 | + } |
346 | + |
347 | + TEST_EQ (pos, strlen (buf)); |
348 | + TEST_EQ (lineno, 3); |
349 | + |
350 | + TEST_ALLOC_SIZE (job, sizeof (JobClass)); |
351 | + |
352 | + TEST_EQ (job->oom_score_adj, 500); |
353 | + |
354 | + nih_free (job); |
355 | + } |
356 | + |
357 | + /* Check that the last of multiple distinct oom stanzas is |
358 | + * used. |
359 | + */ |
360 | + TEST_FEATURE ("with an oom overriding an oom score stanza"); |
361 | + strcpy (buf, "oom score -10\n"); |
362 | + strcat (buf, "oom 10\n"); |
363 | + |
364 | + TEST_ALLOC_FAIL { |
365 | + pos = 0; |
366 | + lineno = 1; |
367 | + job = parse_job (NULL, "test", buf, strlen (buf), |
368 | + &pos, &lineno); |
369 | + |
370 | + if (test_alloc_failed) { |
371 | + TEST_EQ_P (job, NULL); |
372 | + |
373 | + err = nih_error_get (); |
374 | + TEST_EQ (err->number, ENOMEM); |
375 | + nih_free (err); |
376 | + |
377 | + continue; |
378 | + } |
379 | + |
380 | + TEST_EQ (pos, strlen (buf)); |
381 | + TEST_EQ (lineno, 3); |
382 | + |
383 | + TEST_ALLOC_SIZE (job, sizeof (JobClass)); |
384 | + |
385 | + TEST_EQ (job->oom_score_adj, ADJ_TO_SCORE(10)); |
386 | + |
387 | + nih_free (job); |
388 | + } |
389 | + |
390 | + TEST_FEATURE ("with an oom score overriding an oom stanza"); |
391 | + strcpy (buf, "oom -10\n"); |
392 | + strcat (buf, "oom score 10\n"); |
393 | + |
394 | + TEST_ALLOC_FAIL { |
395 | + pos = 0; |
396 | + lineno = 1; |
397 | + job = parse_job (NULL, "test", buf, strlen (buf), |
398 | + &pos, &lineno); |
399 | + |
400 | + if (test_alloc_failed) { |
401 | + TEST_EQ_P (job, NULL); |
402 | + |
403 | + err = nih_error_get (); |
404 | + TEST_EQ (err->number, ENOMEM); |
405 | + nih_free (err); |
406 | + |
407 | + continue; |
408 | + } |
409 | + |
410 | + TEST_EQ (pos, strlen (buf)); |
411 | + TEST_EQ (lineno, 3); |
412 | + |
413 | + TEST_ALLOC_SIZE (job, sizeof (JobClass)); |
414 | + |
415 | + TEST_EQ (job->oom_score_adj, 10); |
416 | |
417 | nih_free (job); |
418 | } |
419 | @@ -6322,6 +6505,25 @@ |
420 | nih_free (err); |
421 | |
422 | |
423 | + /* Check that an oom score stanza without an argument results in a |
424 | + * syntax error. |
425 | + */ |
426 | + TEST_FEATURE ("with missing score argument"); |
427 | + strcpy (buf, "oom score\n"); |
428 | + |
429 | + pos = 0; |
430 | + lineno = 1; |
431 | + job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno); |
432 | + |
433 | + TEST_EQ_P (job, NULL); |
434 | + |
435 | + err = nih_error_get (); |
436 | + TEST_EQ (err->number, NIH_CONFIG_EXPECTED_TOKEN); |
437 | + TEST_EQ (pos, 9); |
438 | + TEST_EQ (lineno, 1); |
439 | + nih_free (err); |
440 | + |
441 | + |
442 | /* Check that an oom stanza with an overly large argument results |
443 | * in a syntax error. |
444 | */ |
445 | @@ -6340,6 +6542,21 @@ |
446 | TEST_EQ (lineno, 1); |
447 | nih_free (err); |
448 | |
449 | + TEST_FEATURE ("with overly large score argument"); |
450 | + strcpy (buf, "oom score 1200\n"); |
451 | + |
452 | + pos = 0; |
453 | + lineno = 1; |
454 | + job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno); |
455 | + |
456 | + TEST_EQ_P (job, NULL); |
457 | + |
458 | + err = nih_error_get (); |
459 | + TEST_EQ (err->number, PARSE_ILLEGAL_OOM); |
460 | + TEST_EQ (pos, 10); |
461 | + TEST_EQ (lineno, 1); |
462 | + nih_free (err); |
463 | + |
464 | |
465 | /* Check that an oom stanza with an overly small argument results |
466 | * in a syntax error. |
467 | @@ -6359,6 +6576,21 @@ |
468 | TEST_EQ (lineno, 1); |
469 | nih_free (err); |
470 | |
471 | + TEST_FEATURE ("with overly small score argument"); |
472 | + strcpy (buf, "oom score -1200\n"); |
473 | + |
474 | + pos = 0; |
475 | + lineno = 1; |
476 | + job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno); |
477 | + |
478 | + TEST_EQ_P (job, NULL); |
479 | + |
480 | + err = nih_error_get (); |
481 | + TEST_EQ (err->number, PARSE_ILLEGAL_OOM); |
482 | + TEST_EQ (pos, 10); |
483 | + TEST_EQ (lineno, 1); |
484 | + nih_free (err); |
485 | + |
486 | |
487 | /* Check that an oom stanza with a non-integer argument results |
488 | * in a syntax error. |
489 | @@ -6378,6 +6610,21 @@ |
490 | TEST_EQ (lineno, 1); |
491 | nih_free (err); |
492 | |
493 | + TEST_FEATURE ("with non-integer score argument"); |
494 | + strcpy (buf, "oom score foo\n"); |
495 | + |
496 | + pos = 0; |
497 | + lineno = 1; |
498 | + job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno); |
499 | + |
500 | + TEST_EQ_P (job, NULL); |
501 | + |
502 | + err = nih_error_get (); |
503 | + TEST_EQ (err->number, PARSE_ILLEGAL_OOM); |
504 | + TEST_EQ (pos, 10); |
505 | + TEST_EQ (lineno, 1); |
506 | + nih_free (err); |
507 | + |
508 | |
509 | /* Check that an oom stanza with a partially numeric argument |
510 | * results in a syntax error. |
511 | @@ -6397,6 +6644,21 @@ |
512 | TEST_EQ (lineno, 1); |
513 | nih_free (err); |
514 | |
515 | + TEST_FEATURE ("with alphanumeric score argument"); |
516 | + strcpy (buf, "oom score 12foo\n"); |
517 | + |
518 | + pos = 0; |
519 | + lineno = 1; |
520 | + job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno); |
521 | + |
522 | + TEST_EQ_P (job, NULL); |
523 | + |
524 | + err = nih_error_get (); |
525 | + TEST_EQ (err->number, PARSE_ILLEGAL_OOM); |
526 | + TEST_EQ (pos, 10); |
527 | + TEST_EQ (lineno, 1); |
528 | + nih_free (err); |
529 | + |
530 | |
531 | /* Check that an oom stanza with a priority but with an extra |
532 | * argument afterwards results in a syntax error. |
533 | @@ -6415,6 +6677,21 @@ |
534 | TEST_EQ (pos, 7); |
535 | TEST_EQ (lineno, 1); |
536 | nih_free (err); |
537 | + |
538 | + TEST_FEATURE ("with extra score argument"); |
539 | + strcpy (buf, "oom score 500 foo\n"); |
540 | + |
541 | + pos = 0; |
542 | + lineno = 1; |
543 | + job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno); |
544 | + |
545 | + TEST_EQ_P (job, NULL); |
546 | + |
547 | + err = nih_error_get (); |
548 | + TEST_EQ (err->number, NIH_CONFIG_UNEXPECTED_TOKEN); |
549 | + TEST_EQ (pos, 14); |
550 | + TEST_EQ (lineno, 1); |
551 | + nih_free (err); |
552 | } |
553 | |
554 | void |