~ubuntu-branches/ubuntu/vivid/slurm-llnl/vivid

« back to all changes in this revision

Viewing changes to src/slurmctld/power_save.c

  • Committer: Bazaar Package Importer
  • Author(s): Gennaro Oliva
  • Date: 2009-09-24 23:28:15 UTC
  • mfrom: (1.1.11 upstream) (3.2.4 sid)
  • Revision ID: james.westby@ubuntu.com-20090924232815-enh65jn32q1ebg07
Tags: 2.0.5-1
* New upstream release 
* Changed dependecy from lib-mysqlclient15 to lib-mysqlclient 
* Added Default-Start for runlevel 2 and 4 and $remote_fs requirement in
  init.d scripts (Closes: #541252)
* Postinst checks for wrong runlevels 2 and 4 links
* Upgraded to standard version 3.8.3
* Add lintian overrides for missing slurm-llnl-configurator.html in doc
  base registration
* modified postrm scripts to ignore pkill return value in order to avoid
  postrm failure when no slurm process is running
* Checking for slurmctld.pid before cancelling running and pending
  jobs during package removal 

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*****************************************************************************\
2
2
 *  power_save.c - support node power saving mode. Nodes which have been 
3
3
 *  idle for an extended period of time will be placed into a power saving 
4
 
 *  mode by running an arbitrary script (typically to set frequency governor).
 
4
 *  mode by running an arbitrary script. This script can lower the voltage
 
5
 *  or frequency of the nodes or can completely power the nodes off.
5
6
 *  When the node is restored to normal operation, another script will be 
6
7
 *  executed. Many parameters are available to control this mode of operation.
7
8
 *****************************************************************************
8
9
 *  Copyright (C) 2007 The Regents of the University of California.
 
10
 *  Copyright (C) 2008-2009 Lawrence Livermore National Security.
9
11
 *  Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
10
12
 *  Written by Morris Jette <jette1@llnl.gov>
11
 
 *  LLNL-CODE-402394.
 
13
 *  CODE-OCEC-09-009. All rights reserved.
12
14
 *  
13
15
 *  This file is part of SLURM, a resource management program.
14
 
 *  For details, see <http://www.llnl.gov/linux/slurm/>.
 
16
 *  For details, see <https://computing.llnl.gov/linux/slurm/>.
 
17
 *  Please also read the included file: DISCLAIMER.
15
18
 *  
16
19
 *  SLURM is free software; you can redistribute it and/or modify it under
17
20
 *  the terms of the GNU General Public License as published by the Free
43
46
#  include "config.h"
44
47
#endif
45
48
 
 
49
#include <signal.h>
 
50
#include <stdlib.h>
 
51
#include <string.h>
 
52
#include <sys/stat.h>
 
53
#include <sys/types.h>
 
54
#include <sys/wait.h>
 
55
#include <time.h>
 
56
#include <unistd.h>
 
57
 
46
58
#include "src/common/bitstring.h"
 
59
#include "src/common/macros.h"
47
60
#include "src/common/xstring.h"
48
61
#include "src/slurmctld/locks.h"
49
62
#include "src/slurmctld/slurmctld.h"
50
63
 
51
 
#include <sys/stat.h>
52
 
#include <sys/types.h>
53
 
#include <sys/wait.h>
54
 
#include <stdlib.h>
55
 
#include <unistd.h>
56
 
 
57
 
#define _DEBUG 0
58
 
 
59
 
int idle_time, suspend_rate, resume_rate;
 
64
#if defined (HAVE_DECL_STRSIGNAL) && !HAVE_DECL_STRSIGNAL
 
65
#  ifndef strsignal
 
66
     extern char *strsignal(int);
 
67
#  endif
 
68
#endif /* defined HAVE_DECL_STRSIGNAL && !HAVE_DECL_STRSIGNAL */
 
69
 
 
70
#define _DEBUG                  0
 
71
#define PID_CNT                 10
 
72
#define MAX_SHUTDOWN_DELAY      120     /* seconds to wait for child procs
 
73
                                         * to exit after daemon shutdown 
 
74
                                         * request, then orphan or kill proc */
 
75
 
 
76
/* Records for tracking processes forked to suspend/resume nodes */
 
77
pid_t  child_pid[PID_CNT];      /* pid of process               */
 
78
time_t child_time[PID_CNT];     /* start time of process        */
 
79
 
 
80
pthread_mutex_t power_mutex = PTHREAD_MUTEX_INITIALIZER;
 
81
bool power_save_enabled = false;
 
82
 
 
83
int idle_time, suspend_rate, resume_timeout, resume_rate, suspend_timeout;
60
84
char *suspend_prog = NULL, *resume_prog = NULL;
61
85
char *exc_nodes = NULL, *exc_parts = NULL;
62
 
time_t last_config = (time_t) 0;
 
86
time_t last_config = (time_t) 0, last_suspend = (time_t) 0;
 
87
uint16_t slurmd_timeout;
63
88
 
64
 
bitstr_t *exc_node_bitmap = NULL;
65
 
int suspend_cnt, resume_cnt;
 
89
bitstr_t *exc_node_bitmap = NULL, *suspend_node_bitmap = NULL;
 
90
int   suspend_cnt,   resume_cnt;
 
91
float suspend_cnt_f, resume_cnt_f;
66
92
 
67
93
static void  _clear_power_config(void);
68
94
static void  _do_power_work(void);
69
95
static void  _do_resume(char *host);
70
96
static void  _do_suspend(char *host);
71
97
static int   _init_power_config(void);
72
 
static void  _kill_zombies(void);
 
98
static void *_init_power_save(void *arg);
 
99
static int   _kill_procs(void);
 
100
static int   _reap_procs(void);
73
101
static void  _re_wake(void);
74
102
static pid_t _run_prog(char *prog, char *arg);
 
103
static void  _shutdown_power(void);
75
104
static bool  _valid_prog(char *file_name);
76
105
 
77
106
/* Perform any power change work to nodes */
80
109
        static time_t last_log = 0, last_work_scan = 0;
81
110
        int i, wake_cnt = 0, sleep_cnt = 0, susp_total = 0;
82
111
        time_t now = time(NULL), delta_t;
83
 
        uint16_t base_state, susp_state;
 
112
        uint16_t base_state, comp_state, susp_state;
84
113
        bitstr_t *wake_node_bitmap = NULL, *sleep_node_bitmap = NULL;
85
114
        struct node_record *node_ptr;
 
115
        bool run_suspend = false;
86
116
 
87
117
        /* Set limit on counts of nodes to have state changed */
88
118
        delta_t = now - last_work_scan;
89
119
        if (delta_t >= 60) {
90
 
                suspend_cnt = 0;
91
 
                resume_cnt  = 0;
 
120
                suspend_cnt_f = 0.0;
 
121
                resume_cnt_f  = 0.0;
92
122
        } else {
93
123
                float rate = (60 - delta_t) / 60.0;
94
 
                suspend_cnt *= rate;
95
 
                resume_cnt  *= rate;
96
 
        }
 
124
                suspend_cnt_f *= rate;
 
125
                resume_cnt_f  *= rate;
 
126
        }
 
127
        suspend_cnt = (suspend_cnt_f + 0.5);
 
128
        resume_cnt  = (resume_cnt_f  + 0.5);
 
129
 
 
130
        if (now > (last_suspend + suspend_timeout)) {
 
131
                /* ready to start another round of node suspends */
 
132
                run_suspend = true;
 
133
                if (last_suspend) {
 
134
                        bit_nclear(suspend_node_bitmap, 0, 
 
135
                                   (node_record_count - 1));
 
136
                        last_suspend = (time_t) 0;
 
137
                }
 
138
        }
 
139
 
97
140
        last_work_scan = now;
98
141
 
99
142
        /* Build bitmaps identifying each node which should change state */
101
144
                node_ptr = &node_record_table_ptr[i];
102
145
                base_state = node_ptr->node_state & NODE_STATE_BASE;
103
146
                susp_state = node_ptr->node_state & NODE_STATE_POWER_SAVE;
 
147
                comp_state = node_ptr->node_state & NODE_STATE_COMPLETING;
104
148
 
105
149
                if (susp_state)
106
150
                        susp_total++;
107
 
                if (susp_state
108
 
                &&  ((suspend_rate == 0) || (suspend_cnt <= suspend_rate))
109
 
                &&  ((base_state == NODE_STATE_ALLOCATED)
110
 
                ||   (node_ptr->last_idle > (now - idle_time)))) {
111
 
                        if (wake_node_bitmap == NULL)
112
 
                                wake_node_bitmap = bit_alloc(node_record_count);
 
151
 
 
152
                /* Resume nodes as appropriate */
 
153
                if (susp_state &&
 
154
                    ((resume_rate == 0) || (resume_cnt < resume_rate))  &&
 
155
                    (bit_test(suspend_node_bitmap, i) == 0)             &&
 
156
                    ((base_state == NODE_STATE_ALLOCATED) ||
 
157
                     (node_ptr->last_idle > (now - idle_time)))) {
 
158
                        if (wake_node_bitmap == NULL) {
 
159
                                wake_node_bitmap = 
 
160
                                        bit_alloc(node_record_count);
 
161
                        }
113
162
                        wake_cnt++;
114
 
                        suspend_cnt++;
 
163
                        resume_cnt++;
 
164
                        resume_cnt_f++;
115
165
                        node_ptr->node_state &= (~NODE_STATE_POWER_SAVE);
 
166
                        bit_clear(power_node_bitmap, i);
 
167
                        node_ptr->node_state   |= NODE_STATE_NO_RESPOND;
 
168
                        node_ptr->last_response = now + resume_timeout;
116
169
                        bit_set(wake_node_bitmap, i);
117
170
                }
118
 
                if ((susp_state == 0)
119
 
                &&  ((resume_rate == 0) || (resume_cnt <= resume_rate))
120
 
                &&  (base_state == NODE_STATE_IDLE)
121
 
                &&  (node_ptr->last_idle < (now - idle_time))
122
 
                &&  ((exc_node_bitmap == NULL) || 
 
171
 
 
172
                /* Suspend nodes as appropriate */
 
173
                if (run_suspend                                         && 
 
174
                    (susp_state == 0)                                   &&
 
175
                    ((suspend_rate == 0) || (suspend_cnt < suspend_rate)) &&
 
176
                    (base_state == NODE_STATE_IDLE)                     &&
 
177
                    (comp_state == 0)                                   &&
 
178
                    (node_ptr->last_idle < (now - idle_time))           &&
 
179
                    ((exc_node_bitmap == NULL) || 
123
180
                     (bit_test(exc_node_bitmap, i) == 0))) {
124
 
                        if (sleep_node_bitmap == NULL)
125
 
                                sleep_node_bitmap = bit_alloc(node_record_count);
 
181
                        if (sleep_node_bitmap == NULL) {
 
182
                                sleep_node_bitmap = 
 
183
                                        bit_alloc(node_record_count);
 
184
                        }
126
185
                        sleep_cnt++;
127
 
                        resume_cnt++;
 
186
                        suspend_cnt++;
 
187
                        suspend_cnt_f++;
128
188
                        node_ptr->node_state |= NODE_STATE_POWER_SAVE;
129
 
                        bit_set(sleep_node_bitmap, i);
 
189
                        bit_set(power_node_bitmap, i);
 
190
                        bit_set(sleep_node_bitmap,   i);
 
191
                        bit_set(suspend_node_bitmap, i);
 
192
                        last_suspend = now;
130
193
                }
131
194
        }
132
 
        if ((now - last_log) > 600) {
133
 
                info("Power save mode %d nodes", susp_total);
 
195
        if (((now - last_log) > 600) && (susp_total > 0)) {
 
196
                info("Power save mode: %d nodes", susp_total);
134
197
                last_log = now;
135
198
        }
136
199
 
137
 
        if ((wake_cnt == 0) && (sleep_cnt == 0))
138
 
                _re_wake();     /* No work to be done now */
139
 
 
140
200
        if (sleep_node_bitmap) {
141
201
                char *nodes;
142
202
                nodes = bitmap2node_name(sleep_node_bitmap);
162
222
        }
163
223
}
164
224
 
165
 
/* Just in case some resume calls failed, re-issue the requests
166
 
 * periodically for active nodes. We do not increment resume_cnt
167
 
 * since there should be no change in power requirements. */
 
225
/* If slurmctld crashes, the node state that it recovers could differ
 
226
 * from the actual hardware state (e.g. ResumeProgram failed to complete).
 
227
 * To address that, when a node that should be powered up for a running 
 
228
 * job is not responding, they try running ResumeProgram again. */
168
229
static void _re_wake(void)
169
230
{
170
 
        static time_t last_wakeup = 0;
171
 
        static int last_inx = 0;
172
 
        time_t now = time(NULL);
 
231
        uint16_t base_state;
173
232
        struct node_record *node_ptr;
174
233
        bitstr_t *wake_node_bitmap = NULL;
175
 
        int i, lim = MIN(node_record_count, 20);
176
 
        uint16_t base_state, susp_state;
177
 
 
178
 
        /* Run at most once per minute */
179
 
        if ((now - last_wakeup) < 60)
180
 
                return;
181
 
        last_wakeup = now;
182
 
 
183
 
        for (i=0; i<lim; i++) {
184
 
                node_ptr = &node_record_table_ptr[last_inx];
 
234
        int i;
 
235
 
 
236
        node_ptr = node_record_table_ptr;
 
237
        for (i=0; i<node_record_count; i++, node_ptr++) {
185
238
                base_state = node_ptr->node_state & NODE_STATE_BASE;
186
 
                susp_state = node_ptr->node_state & NODE_STATE_POWER_SAVE;
187
 
 
188
 
                if ((susp_state == 0) &&
189
 
                    ((base_state == NODE_STATE_ALLOCATED) ||
190
 
                     (base_state == NODE_STATE_IDLE))) {
191
 
                        if (wake_node_bitmap == NULL)
192
 
                                wake_node_bitmap = bit_alloc(node_record_count);
193
 
                        bit_set(wake_node_bitmap, last_inx);
 
239
                if ((base_state == NODE_STATE_ALLOCATED)                  &&
 
240
                    (node_ptr->node_state & NODE_STATE_NO_RESPOND)        &&
 
241
                    ((node_ptr->node_state & NODE_STATE_POWER_SAVE) == 0) &&
 
242
                    (bit_test(suspend_node_bitmap, i) == 0)) {
 
243
                        if (wake_node_bitmap == NULL) {
 
244
                                wake_node_bitmap = 
 
245
                                        bit_alloc(node_record_count);
 
246
                        }
 
247
                        bit_set(wake_node_bitmap, i);
194
248
                }
195
 
                last_inx++;
196
 
                if (last_inx >= node_record_count)
197
 
                        last_inx = 0;
198
249
        }
199
250
 
200
251
        if (wake_node_bitmap) {
201
252
                char *nodes;
202
253
                nodes = bitmap2node_name(wake_node_bitmap);
203
254
                if (nodes) {
204
 
#if _DEBUG
205
255
                        info("power_save: rewaking nodes %s", nodes);
206
 
#else
207
 
                        debug("power_save: rewaking nodes %s", nodes);
208
 
#endif
209
256
                        _run_prog(resume_prog, nodes);  
210
257
                } else
211
258
                        error("power_save: bitmap2nodename");
219
266
#if _DEBUG
220
267
        info("power_save: waking nodes %s", host);
221
268
#else
222
 
        debug("power_save: waking nodes %s", host);
 
269
        verbose("power_save: waking nodes %s", host);
223
270
#endif
224
271
        _run_prog(resume_prog, host);   
225
272
}
229
276
#if _DEBUG
230
277
        info("power_save: suspending nodes %s", host);
231
278
#else
232
 
        debug("power_save: suspending nodes %s", host);
 
279
        verbose("power_save: suspending nodes %s", host);
233
280
#endif
234
281
        _run_prog(suspend_prog, host);  
235
282
}
236
283
 
 
284
/* run a suspend or resume program
 
285
 * prog IN      - program to run
 
286
 * arg IN       - program arguments, the hostlist expression
 
287
 */
237
288
static pid_t _run_prog(char *prog, char *arg)
238
289
{
 
290
        int i;
239
291
        char program[1024], arg0[1024], arg1[1024], *pname;
240
292
        pid_t child;
241
293
 
253
305
 
254
306
        child = fork();
255
307
        if (child == 0) {
256
 
                int i;
257
308
                for (i=0; i<128; i++)
258
309
                        close(i);
 
310
                setpgrp();
259
311
                execl(program, arg0, arg1, NULL);
260
312
                exit(1);
261
 
        } else if (child < 0)
 
313
        } else if (child < 0) {
262
314
                error("fork: %m");
 
315
        } else {
 
316
                /* save the pid */
 
317
                for (i=0; i<PID_CNT; i++) {
 
318
                        if (child_pid[i])
 
319
                                continue;
 
320
                        child_pid[i]  = child;
 
321
                        child_time[i] = time(NULL);
 
322
                        break;
 
323
                }
 
324
                if (i == PID_CNT)
 
325
                        error("power_save: filled child_pid array");
 
326
        }
263
327
        return child;
264
328
}
265
329
 
266
 
/* We don't bother to track individual process IDs, 
267
 
 * just clean everything up here. We could capture 
268
 
 * the value of "child" in _run_prog() if we want 
269
 
 * to track each process. */
270
 
static void  _kill_zombies(void)
271
 
{
272
 
        while (waitpid(-1, NULL, WNOHANG) > 0)
273
 
                ;
 
330
/* reap child processes previously forked to modify node state.
 
331
 * return the count of empty slots in the child_pid array */
 
332
static int  _reap_procs(void)
 
333
{
 
334
        int empties = 0, delay, i, max_timeout, rc, status;
 
335
 
 
336
        max_timeout = MAX(suspend_timeout, resume_timeout);
 
337
        for (i=0; i<PID_CNT; i++) {
 
338
                if (child_pid[i] == 0) {
 
339
                        empties++;
 
340
                        continue;
 
341
                }
 
342
                rc = waitpid(child_pid[i], &status, WNOHANG);
 
343
                if (rc == 0)
 
344
                        continue;
 
345
 
 
346
                delay = difftime(time(NULL), child_time[i]);
 
347
                if (delay > max_timeout) {
 
348
                        info("power_save: program %d ran for %d sec", 
 
349
                             (int) child_pid[i], delay);
 
350
                }
 
351
 
 
352
                if (WIFEXITED(status)) {
 
353
                        rc = WEXITSTATUS(status);
 
354
                        if (rc != 0) {
 
355
                                error("power_save: program exit status of %d", 
 
356
                                      rc);
 
357
                        }
 
358
                } else if (WIFSIGNALED(status)) {
 
359
                        error("power_save: program signalled: %s",
 
360
                              strsignal(WTERMSIG(status)));
 
361
                }
 
362
 
 
363
                child_pid[i]  = 0;
 
364
                child_time[i] = (time_t) 0;
 
365
        }
 
366
        return empties;
 
367
}
 
368
 
 
369
/* kill (or orphan) child processes previously forked to modify node state.
 
370
 * return the count of killed/orphaned processes */
 
371
static int  _kill_procs(void)
 
372
{
 
373
        int killed = 0, i, rc, status;
 
374
 
 
375
        for (i=0; i<PID_CNT; i++) {
 
376
                if (child_pid[i] == 0)
 
377
                        continue;
 
378
 
 
379
                rc = waitpid(child_pid[i], &status, WNOHANG);
 
380
                if (rc == 0) {
 
381
#ifdef  POWER_SAVE_KILL_PROCS
 
382
                        error("power_save: killing process %d",
 
383
                              child_pid[i]);
 
384
                        kill((0-child_pid[i]), SIGKILL);
 
385
#else
 
386
                        error("power_save: orphaning process %d",
 
387
                              child_pid[i]);
 
388
#endif
 
389
                        killed++;
 
390
                } else {
 
391
                        /* process already completed */
 
392
                }
 
393
                child_pid[i]  = 0;
 
394
                child_time[i] = (time_t) 0;
 
395
        }
 
396
        return killed;
 
397
}
 
398
 
 
399
/* shutdown power save daemons */
 
400
static void _shutdown_power(void)
 
401
{
 
402
        int i, proc_cnt, max_timeout;
 
403
 
 
404
        max_timeout = MAX(suspend_timeout, resume_timeout);
 
405
        /* Try to avoid orphan processes */
 
406
        for (i=0; ; i++) {
 
407
                proc_cnt = PID_CNT - _reap_procs();
 
408
                if (proc_cnt == 0)      /* all procs completed */
 
409
                        break;
 
410
                if (i >= max_timeout) {
 
411
                        error("power_save: orphaning %d processes which are "
 
412
                              "not terminating so slurmctld can exit", 
 
413
                              proc_cnt);
 
414
                        _kill_procs();
 
415
                        break;
 
416
                } else if (i == 2) {
 
417
                        info("power_save: waiting for %d processes to "
 
418
                             "complete", proc_cnt);
 
419
                } else if (i % 5 == 0) {
 
420
                        debug("power_save: waiting for %d processes to "
 
421
                              "complete", proc_cnt);
 
422
                }
 
423
                sleep(1);
 
424
        }
274
425
}
275
426
 
276
427
/* Free all allocated memory */
290
441
{
291
442
        slurm_ctl_conf_t *conf = slurm_conf_lock();
292
443
 
293
 
        last_config   = slurmctld_conf.last_update;
294
 
        idle_time     = conf->suspend_time - 1;
295
 
        suspend_rate  = conf->suspend_rate;
296
 
        resume_rate   = conf->resume_rate;
 
444
        last_config     = slurmctld_conf.last_update;
 
445
        idle_time       = conf->suspend_time - 1;
 
446
        suspend_rate    = conf->suspend_rate;
 
447
        resume_timeout  = conf->resume_timeout;
 
448
        resume_rate     = conf->resume_rate;
 
449
        slurmd_timeout  = conf->slurmd_timeout;
 
450
        suspend_timeout = conf->suspend_timeout;
297
451
        _clear_power_config();
298
452
        if (conf->suspend_program)
299
453
                suspend_prog = xstrdup(conf->suspend_program);
306
460
        slurm_conf_unlock();
307
461
 
308
462
        if (idle_time < 0) {    /* not an error */
309
 
                debug("power_save module disabled, idle_time < 0");
 
463
                debug("power_save module disabled, SuspendTime < 0");
310
464
                return -1;
311
465
        }
312
466
        if (suspend_rate < 1) {
313
 
                error("power_save module disabled, suspend_rate < 1");
 
467
                error("power_save module disabled, SuspendRate < 1");
314
468
                return -1;
315
469
        }
316
470
        if (resume_rate < 1) {
317
 
                error("power_save module disabled, resume_rate < 1");
318
 
                return -1;
319
 
        }
320
 
        if (suspend_prog == NULL)
321
 
                info("WARNING: power_save module has NULL suspend program");
322
 
        else if (!_valid_prog(suspend_prog)) {
323
 
                error("power_save module disabled, invalid suspend program %s",
324
 
                        suspend_prog);
325
 
                return -1;
326
 
        }
327
 
        if (resume_prog == NULL)
328
 
                info("WARNING: power_save module has NULL resume program");
329
 
        else if (!_valid_prog(resume_prog)) {
330
 
                error("power_save module disabled, invalid resume program %s",
331
 
                        resume_prog);
 
471
                error("power_save module disabled, ResumeRate < 1");
 
472
                return -1;
 
473
        }
 
474
        if (suspend_prog == NULL) {
 
475
                error("power_save module disabled, NULL SuspendProgram");
 
476
                return -1;
 
477
        } else if (!_valid_prog(suspend_prog)) {
 
478
                error("power_save module disabled, invalid SuspendProgram %s",
 
479
                      suspend_prog);
 
480
                return -1;
 
481
        }
 
482
        if (resume_prog == NULL) {
 
483
                error("power_save module disabled, NULL ResumeProgram");
 
484
                return -1;
 
485
        } else if (!_valid_prog(resume_prog)) {
 
486
                error("power_save module disabled, invalid ResumeProgram %s",
 
487
                      resume_prog);
332
488
                return -1;
333
489
        }
334
490
 
335
 
        if (exc_nodes
336
 
        &&  (node_name2bitmap(exc_nodes, false, &exc_node_bitmap))) {
 
491
        if (exc_nodes &&
 
492
            (node_name2bitmap(exc_nodes, false, &exc_node_bitmap))) {
337
493
                error("power_save module disabled, "
338
 
                        "invalid excluded nodes %s", exc_nodes);
 
494
                      "invalid SuspendExcNodes %s", exc_nodes);
339
495
                return -1;
340
496
        }
341
497
 
350
506
                        part_ptr = find_part_record(one_part);
351
507
                        if (!part_ptr) {
352
508
                                error("power_save module disabled, "
353
 
                                        "invalid excluded partition %s",
 
509
                                        "invalid SuspendExcPart %s",
354
510
                                        one_part);
355
511
                                rc = -1;
356
512
                                break;
358
514
                        if (exc_node_bitmap)
359
515
                                bit_or(exc_node_bitmap, part_ptr->node_bitmap);
360
516
                        else
361
 
                                exc_node_bitmap = bit_copy(part_ptr->node_bitmap);
 
517
                                exc_node_bitmap = bit_copy(part_ptr->
 
518
                                                           node_bitmap);
362
519
                        one_part = strtok_r(NULL, ",", &tmp);
363
520
                }
364
521
                xfree(part_list);
380
537
        struct stat buf;
381
538
 
382
539
        if (file_name[0] != '/') {
383
 
                debug("program %s not absolute pathname", file_name);
 
540
                debug("power_save program %s not absolute pathname", 
 
541
                     file_name);
 
542
                return false;
 
543
        }
 
544
 
 
545
        if (access(file_name, X_OK) != 0) {
 
546
                debug("power_save program %s not executable", file_name);
384
547
                return false;
385
548
        }
386
549
 
387
550
        if (stat(file_name, &buf)) {
388
 
                debug("program %s not found", file_name);
389
 
                return false;
390
 
        }
391
 
        if (!S_ISREG(buf.st_mode)) {
392
 
                debug("program %s not regular file", file_name);
 
551
                debug("power_save program %s not found", file_name);
393
552
                return false;
394
553
        }
395
554
        if (buf.st_mode & 022) {
396
 
                debug("program %s has group or world write permission",
397
 
                        file_name);
 
555
                debug("power_save program %s has group or "
 
556
                      "world write permission",
 
557
                      file_name);
398
558
                return false;
399
559
        }
 
560
 
400
561
        return true;
401
562
}
402
563
 
 
564
/* start_power_mgr - Start power management thread as needed. The thread 
 
565
 *      terminates automatically at slurmctld shutdown time.
 
566
 * IN thread_id - pointer to thread ID of the started pthread. 
 
567
 */
 
568
extern void start_power_mgr(pthread_t *thread_id)
 
569
{
 
570
        pthread_attr_t thread_attr;
 
571
 
 
572
        slurm_mutex_lock(&power_mutex);
 
573
        if (power_save_enabled) {     /* Already running */
 
574
                slurm_mutex_unlock(&power_mutex);
 
575
                return;
 
576
        }
 
577
        power_save_enabled = true;
 
578
        slurm_mutex_unlock(&power_mutex);
 
579
 
 
580
        slurm_attr_init(&thread_attr);
 
581
        while (pthread_create(thread_id, &thread_attr, _init_power_save, 
 
582
                              NULL)) {
 
583
                error("pthread_create %m");
 
584
                sleep(1);
 
585
        }
 
586
        slurm_attr_destroy(&thread_attr);
 
587
}
 
588
 
403
589
/*
404
 
 * init_power_save - initialize the power save module. Started as a
 
590
 * init_power_save - Onitialize the power save module. Started as a
405
591
 *      pthread. Terminates automatically at slurmctld shutdown time.
406
592
 *      Input and output are unused.
407
593
 */
408
 
extern void *init_power_save(void *arg)
 
594
static void *_init_power_save(void *arg)
409
595
{
410
 
        /* Locks: Write node, read jobs and partitions */
 
596
        /* Locks: Read nodes */
 
597
        slurmctld_lock_t node_read_lock = {
 
598
                NO_LOCK, READ_LOCK, NO_LOCK, NO_LOCK };
 
599
        /* Locks: Write nodes */
411
600
        slurmctld_lock_t node_write_lock = {
412
 
                NO_LOCK, READ_LOCK, WRITE_LOCK, READ_LOCK };
413
 
        time_t now, last_power_scan = 0;
 
601
                NO_LOCK, WRITE_LOCK, NO_LOCK, NO_LOCK };
 
602
        time_t now, boot_time = 0, last_power_scan = 0;
414
603
 
415
604
        if (_init_power_config())
416
605
                goto fini;
417
606
 
 
607
        suspend_node_bitmap = bit_alloc(node_record_count);
 
608
        if (suspend_node_bitmap == NULL)
 
609
                fatal("power_save: malloc error");
 
610
 
418
611
        while (slurmctld_config.shutdown_time == 0) {
419
612
                sleep(1);
420
 
                _kill_zombies();
421
 
 
422
 
                if ((last_config != slurmctld_conf.last_update)
423
 
                &&  (_init_power_config()))
 
613
 
 
614
                if (_reap_procs() < 2) {
 
615
                        debug("power_save programs getting backlogged");
 
616
                        continue;
 
617
                }
 
618
 
 
619
                if ((last_config != slurmctld_conf.last_update) &&
 
620
                    (_init_power_config())) {
 
621
                        info("power_save mode has been disabled due to "
 
622
                             "configuration changes");
424
623
                        goto fini;
 
624
                }
425
625
 
426
 
                /* Only run every 60 seconds or after
427
 
                 * a node state change, whichever 
428
 
                 * happens first */
429
626
                now = time(NULL);
430
 
                if ((last_node_update < last_power_scan)
431
 
                &&  (now < (last_power_scan + 60)))
432
 
                        continue;
433
 
 
434
 
                lock_slurmctld(node_write_lock);
435
 
                _do_power_work();
436
 
                unlock_slurmctld(node_write_lock);
437
 
                last_power_scan = now;
 
627
                if (boot_time == 0)
 
628
                        boot_time = now;
 
629
 
 
630
                /* Only run every 60 seconds or after a node state change,
 
631
                 *  whichever happens first */
 
632
                if ((last_node_update >= last_power_scan) ||
 
633
                    (now >= (last_power_scan + 60))) {
 
634
                        lock_slurmctld(node_write_lock);
 
635
                        _do_power_work();
 
636
                        unlock_slurmctld(node_write_lock);
 
637
                        last_power_scan = now;
 
638
                }
 
639
 
 
640
                if (slurmd_timeout &&
 
641
                    (now > (boot_time + (slurmd_timeout / 2)))) {
 
642
                        lock_slurmctld(node_read_lock);
 
643
                        _re_wake();
 
644
                        unlock_slurmctld(node_read_lock);
 
645
                        /* prevent additional executions */
 
646
                        boot_time += (365 * 24 * 60 * 60);
 
647
                        slurmd_timeout = 0;
 
648
                }
438
649
        }
439
650
 
440
651
fini:   _clear_power_config();
 
652
        FREE_NULL_BITMAP(suspend_node_bitmap);
 
653
        _shutdown_power();
 
654
        slurm_mutex_lock(&power_mutex);
 
655
        power_save_enabled = false;
 
656
        slurm_mutex_unlock(&power_mutex);
441
657
        return NULL;
442
658
}