WHATS_NEW_DM | 1 + daemons/dmeventd/dmeventd.c | 61 +++++++++++++++++++++++++++++------------- 2 files changed, 43 insertions(+), 19 deletions(-) diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM index b6a5360..868a469 100644 --- a/WHATS_NEW_DM +++ b/WHATS_NEW_DM @@ -1,5 +1,6 @@ Version 1.02.66 - =============================== + Add support for new oom killer adjustment interface (oom_score_adj). Add systemd unit files for dmeventd. Version 1.02.65 - 8th July 2011 diff --git a/daemons/dmeventd/dmeventd.c b/daemons/dmeventd/dmeventd.c index 1a91cb8..a6956cb 100644 --- a/daemons/dmeventd/dmeventd.c +++ b/daemons/dmeventd/dmeventd.c @@ -41,11 +41,19 @@ #ifdef linux # include -# define OOM_ADJ_FILE "/proc/self/oom_adj" +/* + * Kernel version 2.6.36 and higher has + * new OOM killer adjustment interface. + */ +# define OOM_ADJ_FILE_OLD "/proc/self/oom_adj" +# define OOM_ADJ_FILE "/proc/self/oom_score_adj" /* From linux/oom.h */ +/* Old interface */ # define OOM_DISABLE (-17) # define OOM_ADJUST_MIN (-16) +/* New interface */ +# define OOM_SCORE_ADJ_MIN (-1000) #endif @@ -1594,33 +1602,48 @@ static void _exit_handler(int sig __attribute__((unused))) } #ifdef linux +static int _set_oom_adj(const char *oom_adj_path, int val) +{ + FILE *fp; + + if (!(fp = fopen(oom_adj_path, "w"))) { + perror("oom_adj: fopen failed"); + return 0; + } + + fprintf(fp, "%i", val); + + if (dm_fclose(fp)) + perror("oom_adj: fclose failed"); + + return 1; +} + /* * Protection against OOM killer if kernel supports it */ -static int _set_oom_adj(int val) +static int _protect_against_oom_killer() { - FILE *fp; - struct stat st; if (stat(OOM_ADJ_FILE, &st) == -1) { - if (errno == ENOENT) - perror(OOM_ADJ_FILE " not found"); - else + if (errno != ENOENT) perror(OOM_ADJ_FILE ": stat failed"); - return 1; - } - if (!(fp = fopen(OOM_ADJ_FILE, "w"))) { - perror(OOM_ADJ_FILE ": fopen failed"); - return 0; - } + /* Try old oom_adj interface as a fallback */ + if (stat(OOM_ADJ_FILE_OLD, &st) == -1) { + if (errno == ENOENT) + perror(OOM_ADJ_FILE_OLD " not found"); + else + perror(OOM_ADJ_FILE_OLD ": stat failed"); + return 1; + } - fprintf(fp, "%i", val); - if (dm_fclose(fp)) - perror(OOM_ADJ_FILE ": fclose failed"); + return _set_oom_adj(OOM_ADJ_FILE_OLD, OOM_DISABLE) || + _set_oom_adj(OOM_ADJ_FILE_OLD, OOM_ADJUST_MIN); + } - return 1; + return _set_oom_adj(OOM_ADJ_FILE, OOM_SCORE_ADJ_MIN); } #endif @@ -1829,8 +1852,8 @@ int main(int argc, char *argv[]) signal(SIGQUIT, &_exit_handler); #ifdef linux - if (!_set_oom_adj(OOM_DISABLE) && !_set_oom_adj(OOM_ADJUST_MIN)) - syslog(LOG_ERR, "Failed to set oom_adj to protect against OOM killer"); + if (!_protect_against_oom_killer()) + syslog(LOG_ERR, "Failed to protect against OOM killer"); #endif _init_thread_signals();