Looks good to me on a first pass<br><br><div class="gmail_quote">On Mon, May 2, 2011 at 2:05 PM, Marc - A. Dahlhaus <span dir="ltr"><<a href="mailto:mad@wol.de">mad@wol.de</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<div class="im">Am 17.03.2011 21:48, schrieb Scott James Remnant:<br>
</div><div><div></div><div class="h5">> (Replying to the new patch separately)<br>
><br>
> On Thu, Mar 17, 2011 at 11:58 AM, Marc - A. Dahlhaus <<a href="mailto:mad@wol.de">mad@wol.de</a>> wrote:<br>
><br>
>> The never case was no problem as i set booth values on never.<br>
>> But i get your point. Rewrote it per your comments. Result attached.<br>
>><br>
> This looks perfect, could you add some tests for "oom score" to the<br>
> parsing code, I see you've already updated the existing ones. It also<br>
> needs a man page update (I suggest just dropping "oom NN" out of the<br>
> man page and replacing it with "score")<br>
><br>
> Then it looks ready to apply!<br>
><br>
> Thankyou,<br>
> Scott<br>
<br>
</div></div>This should be it...<br>
<br>
Running for more weeks without any problem here.<br>
<br>
3 Test-Boxes (x86_64 and i686) did several boots, shutdowns and reboots<br>
no problems detected.<br>
<br>
thanks,<br>
<br>
Marc<br>
<div class="im"><br>
--- a/init/errors.h<br>
+++ b/init/errors.h<br>
@@ -62,7 +62,8 @@ enum {<br>
 #define PARSE_ILLEGAL_EXIT_STR         N_("Illegal exit status, expected integer")<br>
 #define PARSE_ILLEGAL_UMASK_STR                N_("Illegal file creation mask,<br>
expected octal integer")<br>
 #define PARSE_ILLEGAL_NICE_STR         N_("Illegal nice value, expected -20 to<br>
19")<br>
-#define PARSE_ILLEGAL_OOM_STR          N_("Illegal oom adjustment, expected -16<br>
to 15 or never")<br>
+#define PARSE_ILLEGAL_OOM_STR          N_("Illegal oom adjustment, expected -16<br>
to 15 or 'never'")<br>
+#define PARSE_ILLEGAL_OOM_SCORE_STR    N_("Illegal oom score adjustment,<br>
expected -999 to 1000 or 'never'")<br>
 #define PARSE_ILLEGAL_LIMIT_STR                N_("Illegal limit, expected<br>
'unlimited' or integer")<br>
 #define PARSE_EXPECTED_EVENT_STR       N_("Expected event")<br>
 #define PARSE_EXPECTED_OPERATOR_STR    N_("Expected operator")<br>
--- a/init/job_class.c<br>
+++ b/init/job_class.c<br>
</div>@@ -211,7 +211,7 @@ job_class_new (const void *parent,<br>
<div class="im"><br>
        class->umask = JOB_DEFAULT_UMASK;<br>
        class->nice = 0;<br>
-       class->oom_adj = 0;<br>
+       class->oom_score_adj = 0;<br>
<br>
        for (i = 0; i < RLIMIT_NLIMITS; i++)<br>
                class->limits[i] = NULL;<br>
</div><div class="im">--- a/init/job_class.h<br>
+++ b/init/job_class.h<br>
</div>@@ -93,7 +93,7 @@ typedef enum console_type {<br>
  * @console: how to arrange processes' stdin/out/err file descriptors,<br>
<div class="im">  * @umask: file mode creation mask,<br>
  * @nice: process priority,<br>
- * @oom_adj: OOM killer adjustment,<br>
+ * @oom_score_adj: OOM killer score adjustment,<br>
  * @limits: resource limits indexed by resource,<br>
  * @chroot: root directory of process (implies @chdir if not set),<br>
  * @chdir: working directory of process,<br>
</div>@@ -141,7 +141,7 @@ typedef struct job_class {<br>
<div class="im"><br>
        mode_t          umask;<br>
        int             nice;<br>
-       int             oom_adj;<br>
+       int             oom_score_adj;<br>
        struct rlimit  *limits[RLIMIT_NLIMITS];<br>
        char           *chroot;<br>
        char           *chdir;<br>
</div>@@ -150,6 +150,8 @@ typedef struct job_class {<br>
        int             debug;<br>
 } JobClass;<br>
<br>
+#define SCORE_TO_ADJ(x) ((x * ((x < 0) ? 17 : 15)) / 1000)<br>
+#define ADJ_TO_SCORE(x) ((x * 1000) / ((x < 0) ? 17 : 15))<br>
<br>
 NIH_BEGIN_EXTERN<br>
<div class="im"><br>
--- a/init/job_process.c<br>
+++ b/init/job_process.c<br>
</div>@@ -371,7 +371,7 @@ job_process_spawn (JobClass     *class,<br>
<div class="im"> {<br>
        sigset_t  child_set, orig_set;<br>
        pid_t     pid;<br>
-       int       i, fds[2];<br>
+       int       i, fds[2], oom_value;<br>
        char      filename[PATH_MAX];<br>
        FILE     *fd;<br>
<br>
</div>@@ -493,16 +493,22 @@ job_process_spawn (JobClass     *class,<br>
<br>
        /* Adjust the process OOM killer priority.<br>
         */<br>
-       if (class->oom_adj) {<br>
+       if (class->oom_score_adj) {<br>
<div class="im">                snprintf (filename, sizeof (filename),<br>
-                         "/proc/%d/oom_adj", getpid ());<br>
</div>-<br>
+                         "/proc/%d/oom_score_adj", getpid ());<br>
+               oom_value = class->oom_score_adj;<br>
                fd = fopen (filename, "w");<br>
+               if ((! fd) && (errno == EACCES)) {<br>
+                       snprintf (filename, sizeof (filename),<br>
<div class="im">+                                 "/proc/%d/oom_adj", getpid ());<br>
</div>+                       oom_value = SCORE_TO_ADJ(class->oom_score_adj);<br>
<div class="im">+                       fd = fopen (filename, "w");<br>
+               }<br>
                if (! fd) {<br>
</div><div class="im">                        nih_error_raise_system ();<br>
                        job_process_error_abort (fds[1], JOB_PROCESS_ERROR_OOM_ADJ, 0);<br>
                } else {<br>
-                       fprintf (fd, "%d\n", class->oom_adj);<br>
+                       fprintf (fd, "%d\n", oom_value);<br>
<br>
                        if (fclose (fd)) {<br>
                                nih_error_raise_system ();<br>
</div>--- a/init/man/init.5<br>
+++ b/init/man/init.5<br>
@@ -500,15 +500,15 @@ see<br>
 for more details.<br>
 .\"<br>
 .TP<br>
-.B oom \fIADJUSTMENT\fR|\fBnever<br>
+.B oom score \fIADJUSTMENT\fR|\fBnever<br>
 Normally the OOM killer regards all processes equally, this stanza<br>
 advises the kernel to treat this job differently.<br>
<br>
 .I ADJUSTMENT<br>
 may be an integer value from<br>
-.I -16<br>
+.I -999<br>
 (very unlikely to be killed by the OOM killer) up to<br>
-.I 14<br>
+.I 1000<br>
 (very likely to be killed by the OOM killer).  It may also be the special<br>
 value<br>
 .B never<br>
<div class="im">--- a/init/parse_job.c<br>
+++ b/init/parse_job.c<br>
</div>@@ -2233,6 +2233,7 @@ stanza_oom (JobClass        *class,<br>
        nih_local char *arg = NULL;<br>
        char           *endptr;<br>
        size_t          a_pos, a_lineno;<br>
+       int             oom_adj;<br>
        int             ret = -1;<br>
<br>
        nih_assert (class != NULL);<br>
@@ -2247,12 +2248,37 @@ stanza_oom (JobClass        *class,<br>
        if (! arg)<br>
                goto finish;<br>
<br>
-       if (! strcmp (arg, "never")) {<br>
-               class->oom_adj = -17;<br>
<div class="im">+       if (! strcmp (arg, "score")) {<br>
+               nih_local char *scorearg = NULL;<br>
+<br>
</div>+               /* Update error position to the score value */<br>
+               *pos = a_pos;<br>
+               if (lineno)<br>
+                       *lineno = a_lineno;<br>
<div class="im">+<br>
+               scorearg = nih_config_next_arg (NULL, file, len,<br>
+                                               &a_pos, &a_lineno);<br>
+               if (! scorearg)<br>
+                       goto finish;<br>
+<br>
+               if (! strcmp (scorearg, "never")) {<br>
+                       class->oom_score_adj = -1000;<br>
</div><div class="im">+               } else {<br>
+                       errno = 0;<br>
+                       class->oom_score_adj = (int)strtol (scorearg, &endptr, 10);<br>
</div><div class="im">+                       if (errno || *endptr ||<br>
+                           (class->oom_score_adj < -1000) ||<br>
+                           (class->oom_score_adj > 1000))<br>
+                               nih_return_error (-1, PARSE_ILLEGAL_OOM,<br>
+                                                 _(PARSE_ILLEGAL_OOM_SCORE_STR));<br>
+               }<br>
</div>+       } else if (! strcmp (arg, "never")) {<br>
<div class="im">+               class->oom_score_adj = -1000;<br>
        } else {<br>
                errno = 0;<br>
-               class->oom_adj = (int)strtol (arg, &endptr, 10);<br>
-               if (errno || *endptr || (class->oom_adj < -17) || (class->oom_adj > 15))<br>
</div>+               oom_adj = (int)strtol (arg, &endptr, 10);<br>
+               class->oom_score_adj = ADJ_TO_SCORE(oom_adj);<br>
+               if (errno || *endptr || (oom_adj < -17) || (oom_adj > 15))<br>
<div class="im">                        nih_return_error (-1, PARSE_ILLEGAL_OOM,<br>
                                          _(PARSE_ILLEGAL_OOM_STR));<br>
        }<br>
</div>--- a/init/tests/test_job_class.c<br>
+++ b/init/tests/test_job_class.c<br>
@@ -133,7 +133,7 @@ test_new (void)<br>
<br>
                TEST_EQ (class->umask, 022);<br>
                TEST_EQ (class->nice, 0);<br>
-               TEST_EQ (class->oom_adj, 0);<br>
+               TEST_EQ (class->oom_score_adj, 0);<br>
<div class="im"><br>
                for (i = 0; i < RLIMIT_NLIMITS; i++)<br>
</div>                        TEST_EQ_P (class->limits[i], NULL);<br>
--- a/init/tests/test_parse_job.c<br>
+++ b/init/tests/test_parse_job.c<br>
@@ -6198,11 +6198,39 @@ test_stanza_oom (void)<br>
<br>
                TEST_ALLOC_SIZE (job, sizeof (JobClass));<br>
<br>
-               TEST_EQ (job->oom_adj, 10);<br>
+               TEST_EQ (job->oom_score_adj, ADJ_TO_SCORE(10));<br>
<br>
                nih_free (job);<br>
        }<br>
<br>
+       TEST_FEATURE ("with positive score argument");<br>
+       strcpy (buf, "oom score 100\n");<br>
+<br>
+       TEST_ALLOC_FAIL {<br>
+               pos = 0;<br>
+               lineno = 1;<br>
+               job = parse_job (NULL, "test", buf, strlen (buf),<br>
+                                &pos, &lineno);<br>
+<br>
+               if (test_alloc_failed) {<br>
+                       TEST_EQ_P (job, NULL);<br>
+<br>
+                       err = nih_error_get ();<br>
+                       TEST_EQ (err->number, ENOMEM);<br>
+                       nih_free (err);<br>
+<br>
+                       continue;<br>
+               }<br>
+<br>
+               TEST_EQ (pos, strlen (buf));<br>
+               TEST_EQ (lineno, 2);<br>
+<br>
+               TEST_ALLOC_SIZE (job, sizeof (JobClass));<br>
+<br>
+               TEST_EQ (job->oom_score_adj, 100);<br>
+<br>
+               nih_free (job);<br>
+       }<br>
<br>
        /* Check that an oom stanza with a negative timeout results<br>
         * in it being stored in the job.<br>
@@ -6231,7 +6259,36 @@ test_stanza_oom (void)<br>
<br>
                TEST_ALLOC_SIZE (job, sizeof (JobClass));<br>
<br>
-               TEST_EQ (job->oom_adj, -10);<br>
+               TEST_EQ (job->oom_score_adj, ADJ_TO_SCORE(-10));<br>
+<br>
+               nih_free (job);<br>
+       }<br>
+<br>
+       TEST_FEATURE ("with negative score argument");<br>
+       strcpy (buf, "oom score -100\n");<br>
+<br>
+       TEST_ALLOC_FAIL {<br>
+               pos = 0;<br>
+               lineno = 1;<br>
+               job = parse_job (NULL, "test", buf, strlen (buf),<br>
+                                &pos, &lineno);<br>
+<br>
+               if (test_alloc_failed) {<br>
+                       TEST_EQ_P (job, NULL);<br>
+<br>
+                       err = nih_error_get ();<br>
+                       TEST_EQ (err->number, ENOMEM);<br>
+                       nih_free (err);<br>
+<br>
+                       continue;<br>
+               }<br>
+<br>
+               TEST_EQ (pos, strlen (buf));<br>
+               TEST_EQ (lineno, 2);<br>
+<br>
+               TEST_ALLOC_SIZE (job, sizeof (JobClass));<br>
+<br>
+               TEST_EQ (job->oom_score_adj, -100);<br>
<br>
                nih_free (job);<br>
        }<br>
@@ -6264,7 +6321,40 @@ test_stanza_oom (void)<br>
<br>
                TEST_ALLOC_SIZE (job, sizeof (JobClass));<br>
<br>
-               TEST_EQ (job->oom_adj, -17);<br>
+               TEST_EQ (job->oom_score_adj, ADJ_TO_SCORE(-17));<br>
+<br>
+               nih_free (job);<br>
+       }<br>
+<br>
+<br>
+       /* Check that an oom score stanza may have the special never<br>
+        *  argument which stores -1000 in the job.<br>
+        */<br>
+       TEST_FEATURE ("with never score argument");<br>
+       strcpy (buf, "oom score never\n");<br>
+<br>
+       TEST_ALLOC_FAIL {<br>
+               pos = 0;<br>
+               lineno = 1;<br>
+               job = parse_job (NULL, "test", buf, strlen (buf),<br>
+                                &pos, &lineno);<br>
+<br>
+               if (test_alloc_failed) {<br>
+                       TEST_EQ_P (job, NULL);<br>
+<br>
+                       err = nih_error_get ();<br>
+                       TEST_EQ (err->number, ENOMEM);<br>
+                       nih_free (err);<br>
+<br>
+                       continue;<br>
+               }<br>
+<br>
+               TEST_EQ (pos, strlen (buf));<br>
+               TEST_EQ (lineno, 2);<br>
+<br>
+               TEST_ALLOC_SIZE (job, sizeof (JobClass));<br>
+<br>
+               TEST_EQ (job->oom_score_adj, -1000);<br>
<br>
                nih_free (job);<br>
        }<br>
@@ -6297,7 +6387,100 @@ test_stanza_oom (void)<br>
<br>
                TEST_ALLOC_SIZE (job, sizeof (JobClass));<br>
<br>
-               TEST_EQ (job->oom_adj, 10);<br>
+               TEST_EQ (job->oom_score_adj, ADJ_TO_SCORE(10));<br>
+<br>
+               nih_free (job);<br>
+       }<br>
+<br>
+       TEST_FEATURE ("with multiple score stanzas");<br>
+       strcpy (buf, "oom score -500\n");<br>
+       strcat (buf, "oom score 500\n");<br>
+<br>
+       TEST_ALLOC_FAIL {<br>
+               pos = 0;<br>
+               lineno = 1;<br>
+               job = parse_job (NULL, "test", buf, strlen (buf),<br>
+                                &pos, &lineno);<br>
+<br>
+               if (test_alloc_failed) {<br>
+                       TEST_EQ_P (job, NULL);<br>
+<br>
+                       err = nih_error_get ();<br>
+                       TEST_EQ (err->number, ENOMEM);<br>
+                       nih_free (err);<br>
+<br>
+                       continue;<br>
+               }<br>
+<br>
+               TEST_EQ (pos, strlen (buf));<br>
+               TEST_EQ (lineno, 3);<br>
+<br>
+               TEST_ALLOC_SIZE (job, sizeof (JobClass));<br>
+<br>
+               TEST_EQ (job->oom_score_adj, 500);<br>
+<br>
+               nih_free (job);<br>
+       }<br>
+<br>
+       /* Check that the last of multiple distinct oom stanzas is<br>
+        * used.<br>
+        */<br>
+       TEST_FEATURE ("with an oom overriding an oom score stanza");<br>
+       strcpy (buf, "oom score -10\n");<br>
+       strcat (buf, "oom 10\n");<br>
+<br>
+       TEST_ALLOC_FAIL {<br>
+               pos = 0;<br>
+               lineno = 1;<br>
+               job = parse_job (NULL, "test", buf, strlen (buf),<br>
+                                &pos, &lineno);<br>
+<br>
+               if (test_alloc_failed) {<br>
+                       TEST_EQ_P (job, NULL);<br>
+<br>
+                       err = nih_error_get ();<br>
+                       TEST_EQ (err->number, ENOMEM);<br>
+                       nih_free (err);<br>
+<br>
+                       continue;<br>
+               }<br>
+<br>
+               TEST_EQ (pos, strlen (buf));<br>
+               TEST_EQ (lineno, 3);<br>
+<br>
+               TEST_ALLOC_SIZE (job, sizeof (JobClass));<br>
+<br>
+               TEST_EQ (job->oom_score_adj, ADJ_TO_SCORE(10));<br>
+<br>
+               nih_free (job);<br>
+       }<br>
+<br>
+       TEST_FEATURE ("with an oom score overriding an oom stanza");<br>
+       strcpy (buf, "oom -10\n");<br>
+       strcat (buf, "oom score 10\n");<br>
+<br>
+       TEST_ALLOC_FAIL {<br>
+               pos = 0;<br>
+               lineno = 1;<br>
+               job = parse_job (NULL, "test", buf, strlen (buf),<br>
+                                &pos, &lineno);<br>
+<br>
+               if (test_alloc_failed) {<br>
+                       TEST_EQ_P (job, NULL);<br>
+<br>
+                       err = nih_error_get ();<br>
+                       TEST_EQ (err->number, ENOMEM);<br>
+                       nih_free (err);<br>
+<br>
+                       continue;<br>
+               }<br>
+<br>
+               TEST_EQ (pos, strlen (buf));<br>
+               TEST_EQ (lineno, 3);<br>
+<br>
+               TEST_ALLOC_SIZE (job, sizeof (JobClass));<br>
+<br>
+               TEST_EQ (job->oom_score_adj, 10);<br>
<br>
                nih_free (job);<br>
        }<br>
@@ -6322,6 +6505,25 @@ test_stanza_oom (void)<br>
        nih_free (err);<br>
<br>
<br>
+       /* Check that an oom score stanza without an argument results in a<br>
+        * syntax error.<br>
+        */<br>
+       TEST_FEATURE ("with missing score argument");<br>
+       strcpy (buf, "oom score\n");<br>
+<br>
+       pos = 0;<br>
+       lineno = 1;<br>
+       job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);<br>
+<br>
+       TEST_EQ_P (job, NULL);<br>
+<br>
+       err = nih_error_get ();<br>
+       TEST_EQ (err->number, NIH_CONFIG_EXPECTED_TOKEN);<br>
+       TEST_EQ (pos, 9);<br>
+       TEST_EQ (lineno, 1);<br>
+       nih_free (err);<br>
+<br>
+<br>
        /* Check that an oom stanza with an overly large argument results<br>
         * in a syntax error.<br>
         */<br>
@@ -6340,6 +6542,21 @@ test_stanza_oom (void)<br>
        TEST_EQ (lineno, 1);<br>
        nih_free (err);<br>
<br>
+       TEST_FEATURE ("with overly large score argument");<br>
+       strcpy (buf, "oom score 1200\n");<br>
+<br>
+       pos = 0;<br>
+       lineno = 1;<br>
+       job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);<br>
+<br>
+       TEST_EQ_P (job, NULL);<br>
+<br>
+       err = nih_error_get ();<br>
+       TEST_EQ (err->number, PARSE_ILLEGAL_OOM);<br>
+       TEST_EQ (pos, 10);<br>
+       TEST_EQ (lineno, 1);<br>
+       nih_free (err);<br>
+<br>
<br>
        /* Check that an oom stanza with an overly small argument results<br>
         * in a syntax error.<br>
@@ -6359,6 +6576,21 @@ test_stanza_oom (void)<br>
        TEST_EQ (lineno, 1);<br>
        nih_free (err);<br>
<br>
+       TEST_FEATURE ("with overly small score argument");<br>
+       strcpy (buf, "oom score -1200\n");<br>
+<br>
+       pos = 0;<br>
+       lineno = 1;<br>
+       job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);<br>
+<br>
+       TEST_EQ_P (job, NULL);<br>
+<br>
+       err = nih_error_get ();<br>
+       TEST_EQ (err->number, PARSE_ILLEGAL_OOM);<br>
+       TEST_EQ (pos, 10);<br>
+       TEST_EQ (lineno, 1);<br>
+       nih_free (err);<br>
+<br>
<br>
        /* Check that an oom stanza with a non-integer argument results<br>
         * in a syntax error.<br>
@@ -6378,6 +6610,21 @@ test_stanza_oom (void)<br>
        TEST_EQ (lineno, 1);<br>
        nih_free (err);<br>
<br>
+       TEST_FEATURE ("with non-integer score argument");<br>
+       strcpy (buf, "oom score foo\n");<br>
+<br>
+       pos = 0;<br>
+       lineno = 1;<br>
+       job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);<br>
+<br>
+       TEST_EQ_P (job, NULL);<br>
+<br>
+       err = nih_error_get ();<br>
+       TEST_EQ (err->number, PARSE_ILLEGAL_OOM);<br>
+       TEST_EQ (pos, 10);<br>
+       TEST_EQ (lineno, 1);<br>
+       nih_free (err);<br>
+<br>
<br>
        /* Check that an oom stanza with a partially numeric argument<br>
         * results in a syntax error.<br>
@@ -6397,6 +6644,21 @@ test_stanza_oom (void)<br>
        TEST_EQ (lineno, 1);<br>
        nih_free (err);<br>
<br>
+       TEST_FEATURE ("with alphanumeric score argument");<br>
+       strcpy (buf, "oom score 12foo\n");<br>
+<br>
+       pos = 0;<br>
+       lineno = 1;<br>
+       job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);<br>
+<br>
+       TEST_EQ_P (job, NULL);<br>
+<br>
+       err = nih_error_get ();<br>
+       TEST_EQ (err->number, PARSE_ILLEGAL_OOM);<br>
+       TEST_EQ (pos, 10);<br>
+       TEST_EQ (lineno, 1);<br>
+       nih_free (err);<br>
+<br>
<br>
        /* Check that an oom stanza with a priority but with an extra<br>
         * argument afterwards results in a syntax error.<br>
@@ -6415,6 +6677,21 @@ test_stanza_oom (void)<br>
        TEST_EQ (pos, 7);<br>
        TEST_EQ (lineno, 1);<br>
        nih_free (err);<br>
+<br>
+       TEST_FEATURE ("with extra score argument");<br>
+       strcpy (buf, "oom score 500 foo\n");<br>
+<br>
+       pos = 0;<br>
+       lineno = 1;<br>
+       job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);<br>
+<br>
+       TEST_EQ_P (job, NULL);<br>
+<br>
+       err = nih_error_get ();<br>
+       TEST_EQ (err->number, NIH_CONFIG_UNEXPECTED_TOKEN);<br>
+       TEST_EQ (pos, 14);<br>
+       TEST_EQ (lineno, 1);<br>
+       nih_free (err);<br>
 }<br>
<br>
 void<br>
</blockquote></div><br>