From 73d58a7c780620e2963a16a3179556337166c032 Mon Sep 17 00:00:00 2001 From: Mehdi Dogguy <mehdi@debian.org> Date: Mon, 8 Sep 2014 21:38:48 +0200 Subject: [PATCH] Imported Upstream version 2.2.4 --- META | 4 +- NEWS | 160 ++++- RELEASE_NOTES | 8 +- auxdir/x_ac_debug.m4 | 22 +- config.h.in | 3 + configure | 73 +- configure.ac | 3 +- contribs/perlapi/libslurm/Makefile.am | 8 +- contribs/perlapi/libslurm/Makefile.in | 8 +- contribs/perlapi/libslurmdb/Makefile.am | 6 +- contribs/perlapi/libslurmdb/Makefile.in | 6 +- doc/html/Makefile.am | 1 + doc/html/Makefile.in | 1 + doc/html/bluegene.shtml | 22 + doc/html/documentation.shtml | 1 + doc/html/multi_cluster.shtml | 61 ++ doc/html/reservations.shtml | 3 +- doc/man/man1/sacct.1 | 7 + doc/man/man1/sacctmgr.1 | 17 +- doc/man/man1/salloc.1 | 59 +- doc/man/man1/sbatch.1 | 58 +- doc/man/man1/scancel.1 | 18 +- doc/man/man1/scontrol.1 | 33 +- doc/man/man1/squeue.1 | 4 + doc/man/man1/srun.1 | 64 +- doc/man/man5/slurm.conf.5 | 36 +- slurm.spec | 9 +- src/api/job_info.c | 17 +- src/common/assoc_mgr.c | 49 +- src/common/env.c | 5 +- src/common/pack.c | 32 +- src/common/parse_config.c | 16 +- src/common/parse_time.c | 2 +- src/common/read_config.c | 39 ++ src/common/read_config.h | 10 + src/common/slurm_protocol_api.c | 2 +- src/common/slurm_protocol_defs.c | 38 +- src/common/slurm_step_layout.c | 57 +- .../filetxt/accounting_storage_filetxt.c | 75 ++- .../mysql/accounting_storage_mysql.c | 113 +++- .../mysql/accounting_storage_mysql.h | 3 +- .../accounting_storage/mysql/as_mysql_assoc.c | 29 +- .../mysql/as_mysql_cluster.c | 2 +- .../mysql/as_mysql_convert.c | 4 +- .../accounting_storage/mysql/as_mysql_job.c | 12 +- .../accounting_storage/mysql/as_mysql_qos.c | 55 +- .../accounting_storage/mysql/as_mysql_txn.c | 1 - src/plugins/job_submit/Makefile.am | 2 +- src/plugins/job_submit/Makefile.in | 4 +- src/plugins/job_submit/cnode/Makefile.am | 13 + src/plugins/job_submit/cnode/Makefile.in | 637 ++++++++++++++++++ .../job_submit/cnode/job_submit_cnode.c | 184 +++++ src/plugins/jobcomp/filetxt/jobcomp_filetxt.c | 4 + src/plugins/jobcomp/mysql/jobcomp_mysql.c | 6 +- src/plugins/jobcomp/pgsql/jobcomp_pgsql.c | 6 +- src/plugins/jobcomp/script/jobcomp_script.c | 8 +- src/plugins/sched/backfill/backfill.c | 39 +- src/plugins/sched/builtin/builtin.c | 2 +- .../select/bluegene/plugin/bg_job_place.c | 39 +- .../select/bluegene/plugin/bg_job_run.c | 48 +- .../bluegene/plugin/bg_record_functions.c | 6 + src/plugins/select/bluegene/plugin/bluegene.c | 259 +++---- .../select/bluegene/plugin/dynamic_block.c | 10 +- src/plugins/select/bluegene/plugin/jobinfo.c | 7 +- src/plugins/select/bluegene/plugin/nodeinfo.c | 5 +- src/plugins/select/cons_res/job_test.c | 48 +- src/plugins/select/cons_res/select_cons_res.c | 10 +- src/plugins/task/affinity/dist_tasks.c | 33 +- src/plugins/task/affinity/task_affinity.c | 3 +- src/plugins/task/none/task_none.c | 3 +- src/sacct/options.c | 25 +- src/sacctmgr/archive_functions.c | 39 +- src/sacctmgr/cluster_functions.c | 8 +- src/sacctmgr/event_functions.c | 24 +- src/sacctmgr/file_functions.c | 8 +- src/sacctmgr/qos_functions.c | 2 + src/sacctmgr/user_functions.c | 25 +- src/salloc/salloc.c | 67 +- src/sbatch/mult_cluster.c | 13 +- src/scancel/opt.c | 15 +- src/scancel/scancel.c | 19 +- src/scontrol/scontrol.c | 135 ++-- src/scontrol/update_job.c | 2 +- src/slurmctld/acct_policy.c | 538 +++++++-------- src/slurmctld/acct_policy.h | 2 +- src/slurmctld/controller.c | 1 + src/slurmctld/gang.c | 24 +- src/slurmctld/job_mgr.c | 30 +- src/slurmctld/job_scheduler.c | 38 +- src/slurmctld/job_scheduler.h | 3 +- src/slurmctld/node_mgr.c | 47 +- src/slurmctld/node_scheduler.c | 40 +- src/slurmctld/reservation.c | 76 ++- src/slurmctld/slurmctld.h | 2 +- src/slurmctld/step_mgr.c | 40 +- src/slurmd/slurmd/req.c | 44 +- src/slurmd/slurmd/slurmd.c | 5 +- src/smap/partition_functions.c | 22 +- src/squeue/opts.c | 38 +- src/squeue/print.c | 46 +- src/sreport/job_reports.c | 41 +- src/strigger/opts.c | 16 +- src/sview/block_info.c | 13 +- src/sview/grid.c | 2 +- src/sview/node_info.c | 1 + src/sview/part_info.c | 1 + src/sview/resv_info.c | 16 + src/sview/sview.c | 2 +- testsuite/expect/test1.26 | 8 +- testsuite/expect/test1.84 | 13 +- testsuite/expect/test6.13 | 1 + testsuite/expect/test7.2.prog.c | 2 +- testsuite/expect/test9.7 | 6 +- 113 files changed, 2965 insertions(+), 1167 deletions(-) create mode 100644 doc/html/multi_cluster.shtml create mode 100644 src/plugins/job_submit/cnode/Makefile.am create mode 100644 src/plugins/job_submit/cnode/Makefile.in create mode 100644 src/plugins/job_submit/cnode/job_submit_cnode.c diff --git a/META b/META index a63286038..b1dce6bbb 100644 --- a/META +++ b/META @@ -3,9 +3,9 @@ Api_revision: 0 Major: 2 Meta: 1 - Micro: 1 + Micro: 4 Minor: 2 Name: slurm Release: 1 Release_tags: dist - Version: 2.2.1 + Version: 2.2.4 diff --git a/NEWS b/NEWS index 0146d4dbd..122e63a2a 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,160 @@ This file describes changes in recent versions of SLURM. It primarily documents those changes that are of interest to users and admins. +* Changes in SLURM 2.2.4 +======================== + -- For batch jobs for which the Prolog fails, substitute the job ID for any + "%j" in the job's output or error file specification. + -- Add licenses field to the sview reservation information. + -- BLUEGENE - Fix for handling extremely overloaded system on Dynamic system + dealing with starting jobs on overlapping blocks. Previous fallout + was job would be requeued. (happens very rarely) + -- In accounting_storage/filetxt plugin, substitute spaces within job names, + step names, and account names with an underscore to insure proper parsing. + -- When building contribs/perlapi ignore both INSTALL_BASE and PERL_MM_OPT. + Use PREFIX instead to avoid build errors from multiple installation + specifications. + -- Add job_submit/cnode plugin to support resource reservations of less than + a full midplane on BlueGene computers. Treat cnodes as liceses which can + be reserved and are consumed by jobs. This reservation mechanism for less + than an entire midplane is still under development. + -- Clear a job's "reason" field when a held job is released. + -- When releasing a held job, calculate a new priority for it rather than + just setting the priority to 1. + -- Fix for sview started on a non-bluegene system to pick colors correctly + when talking to a real bluegene system. + -- Improve sched/backfill's expected start time calculation. + -- Prevent abort of sacctmgr for dump command with invalid (or no) filename. + -- Improve handling of job updates when using limits in accounting, and + updating jobs as a non-admin user. + -- Fix for "squeue --states=all" option. Bug would show no jobs. + -- Schedule jobs with reservations before those without reservations. + -- Fix squeue/scancel to query correctly against accounts of different case. + -- Abort an srun command when it's associated job gets aborted due to a + dependency that can not be satisfied. + -- In jobcomp plugins, report start time of zeroif pending job is cancelled. + Previously may report expected start time. + -- Fixed sacctmgr man to state correct variables. + -- Select nodes based upon their Weight when job allocation requests include + a constraint field with a count (e.g. "srun --constraint=gpu*2 -N4 a.out"). + -- Add support for user names that are entirely numeric and do not treat them + as UID values. Patch from Dennis Leepow. + -- Patch to un/pack double values properly if negative value. Patch from + Dennis Leepow + -- Do not reset a job's priority when requeued or suspended. + -- Fix problemm that could let new jobs start on a node in DRAINED state. + -- Fix cosmetic sacctmgr issue where if the user you are trying to add + doesn't exist in the /etc/passwd file and the account you are trying + to add them to doesn't exist it would print (null) instead of the bad + account name. + -- Fix associations/qos for when adding back a previously deleted object + the object will be cleared of all old limits. + -- BLUEGENE - Added back a lock when creating dynamic blocks to be more thread + safe on larger systems with heavy load. + +* Changes in SLURM 2.2.3 +======================== + -- Update srun, salloc, and sbatch man page description of --distribution + option. Patches from Rod Schulz, Bull. + -- Applied patch from Martin Perry to fix "Incorrect results for task/affinity + block second distribution and cpus-per-task > 1" bug. + -- Avoid setting a job's eligible time while held (priority == 0). + -- Substantial performance improvement to backfill scheduling. Patch from + Bjorn-Helge Mevik, University of Oslo. + -- Make timeout for communications to the slurmctld be based upon the + MessageTimeout configuration parameter rather than always 3 seconds. + Patch from Matthieu Hautreux, CEA. + -- Add new scontrol option of "show aliases" to report every NodeName that is + associated with a given NodeHostName when running multiple slurmd daemons + per compute node (typically used for testing purposes). Patch from + Matthieu Hautreux, CEA. + -- Fix for handling job names with a "'" in the name within MySQL accounting. + Patch from Gerrit Renker, CSCS. + -- Modify condition under which salloc execution delayed until moved to the + foreground. Patch from Gerrit Renker, CSCS. + Job control for interactive salloc sessions: only if ... + a) input is from a terminal (stdin has valid termios attributes), + b) controlling terminal exists (non-negative tpgid), + c) salloc is not run in allocation-only (--no-shell) mode, + d) salloc runs in its own process group (true in interactive + shells that support job control), + e) salloc has been configured at compile-time to support background + execution and is not currently in the background process group. + -- Abort salloc if no controlling terminal and --no-shell option is not used + ("setsid salloc ..." is disabled). Patch from Gerrit Renker, CSCS. + -- Fix to gang scheduling logic which could cause jobs to not be suspended + or resumed when appropriate. + -- Applied patch from Martin Perry to fix "Slurmd abort when using task + affinity with plane distribution" bug. + -- Applied patch from Yiannis Georgiou to fix "Problem with cpu binding to + sockets option" behaviour. This change causes "--cpu_bind=sockets" to bind + tasks only to the CPUs on each socket allocated to the job rather than all + CPUs on each socket. + -- Advance daily or weekly reservations immediately after termination to avoid + having a job start that runs into the reservation when later advanced. + -- Fix for enabling users to change there own default account, wckey, or QOS. + -- BLUEGENE - If using OVERLAP mode fixed issue with multiple overlapping + blocks in error mode. + -- Fix for sacctmgr to display correctly default accounts. + -- scancel -s SIGKILL will always sent the RPC to the slurmctld rather than + the slurmd daemon(s). This insures that tasks in the process of getting + spawned are killed. + -- BLUEGENE - If using OVERLAP mode fixed issue with jobs getting denied + at submit if the only option for their job was overlapping a block in + error state. + +* Changes in SLURM 2.2.2 +======================== + -- Correct logic to set correct job hold state (admin or user) when setting + the job's priority using scontrol's "update jobid=..." rather than its + "hold" or "holdu" commands. + -- Modify squeue to report unset --mincores, --minthreads or --extra-node-info + values as "*" rather than 65534. Patch from Rod Schulz, BULL. + -- Report the StartTime of a job as "Unknown" rather than the year 2106 if its + expected start time was too far in the future for the backfill scheduler + to compute. + -- Prevent a pending job reason field from inappropriately being set to + "Priority". + -- In sched/backfill with jobs having QOS_FLAG_NO_RESERVE set, then don't + consider the job's time limit when attempting to backfill schedule. The job + will just be preempted as needed at any time. + -- Eliminated a bug in sbatch when no valid target clusters are specified. + -- When explicitly sending a signal to a job with the scancel command and that + job is in a pending state, then send the request directly to the slurmctld + daemon and do not attempt to send the request to slurmd daemons, which are + not running the job anyway. + -- In slurmctld, properly set the up_node_bitmap when setting it's state to + IDLE (in case the previous node state was DOWN). + -- Fix smap to process block midplane names correctly when on a bluegene + system. + -- Fix smap to once again print out the Letter 'ID' for each line of a block/ + partition view. + -- Corrected the NOTES section of the scancel man page + -- Fix for accounting_storage/mysql plugin to correctly query cluster based + transactions. + -- Fix issue when updating database for clusters that were previously deleted + before upgrade to 2.2 database. + -- BLUEGENE - Handle mesh torus check better in dynamic mode. + -- BLUEGENE - Fixed race condition when freeing block, most likely only would + happen in emulation. + -- Fix for calculating used QOS limits correctly on a slurmctld reconfig. + -- BLUEGENE - Fix for bad conn-type set when running small blocks in HTC mode. + -- If salloc's --no-shell option is used, then do not attempt to preserve the + terminal's state. + -- Add new SLURM configure time parameter of --disable-salloc-background. If + set, then salloc can only execute in the foreground. If started in the + background, then a message will be printed and the job allocation halted + until brought into the foreground. + NOTE: THIS IS A CHANGE IN DEFAULT SALLOC BEHAVIOR FROM V2.2.1, BUT IS + CONSISTENT WITH V2.1 AND EARLIER. + -- Added the Multi-Cluster Operation web page. + -- Removed remnant code for enforcing max sockets/cores/threads in the + cons_res plugin (see last item in 2.1.0-pre5). This was responsible + for a bug reported by Rod Schultz. + -- BLUEGENE - Set correct env vars for HTC mode on a P system to get correct + block. + -- Correct RunTime reported by "scontrol show job" for pending jobs. + * Changes in SLURM 2.2.1 ======================== -- Fix setting derived exit code correctly for jobs that happen to have the @@ -612,10 +766,10 @@ documents those changes that are of interest to users and admins. -- Add scontrol "wait_job <job_id>" option to wait for nodes to boot as needed. Useful for batch jobs (in Prolog, PrologSlurmctld or the script) if powering down idle nodes. - -- Added salloc and sbatch option --wait-for-nodes. If set non-zero, job + -- Added salloc and sbatch option --wait-all-nodes. If set non-zero, job initiation will be delayed until all allocated nodes have booted. Salloc will log the delay with the messages "Waiting for nodes to boot" and "Nodes - are ready for use". + are ready for job". -- The Priority/mulitfactor plugin now takes into consideration size of job in cpus as well as size in nodes when looking at the job size factor. Previously only nodes were considered. @@ -6091,4 +6245,4 @@ documents those changes that are of interest to users and admins. -- Change directory to /tmp in slurmd if daemonizing. -- Logfiles are reopened on reconfigure. -$Id: NEWS 22224 2011-01-26 23:41:18Z da $ +$Id: NEWS 22954 2011-03-30 16:14:50Z da $ diff --git a/RELEASE_NOTES b/RELEASE_NOTES index 481a267b3..d7a6c2951 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -158,10 +158,10 @@ COMMAND CHANGES (see man pages for details) * srun's --core option has been removed. Use the SPANK "Core" plugin from http://code.google.com/p/slurm-spank-plugins/ for continued support. -* Added salloc and sbatch option --wait-for-nodes. If set non-zero, job +* Added salloc and sbatch option --wait-all-nodes. If set non-zero, job initiation will be delayed until all allocated nodes have booted. Salloc will log the delay with the messages "Waiting for nodes to boot" and "Nodes - are ready for use". + are ready for job". * Added scontrol "wait_job <job_id>" option to wait for nodes to boot as needed. Useful for batch jobs (in Prolog, PrologSlurmctld or the script) if powering @@ -177,6 +177,10 @@ COMMAND CHANGES (see man pages for details) job specifies it's memory requirement, then more CPUs than requested will automatically be allocated to a job to honor the MaxMemPerCPU parameter. +* Add new scontrol option of "show aliases" to report every NodeName that is + associated with a given NodeHostName when running multiple slurmd daemons + per compute node (typically used for testing purposes). + BLUEGENE SPECIFIC CHANGES ========================= diff --git a/auxdir/x_ac_debug.m4 b/auxdir/x_ac_debug.m4 index 4eec4cf0d..f8cc7ee6d 100644 --- a/auxdir/x_ac_debug.m4 +++ b/auxdir/x_ac_debug.m4 @@ -1,5 +1,5 @@ ##***************************************************************************** -# $Id: x_ac_debug.m4 21164 2010-09-15 22:47:29Z jette $ +# $Id: x_ac_debug.m4 22484 2011-02-15 19:14:24Z jette $ ##***************************************************************************** # AUTHOR: # Chris Dunlap <cdunlap@llnl.gov> @@ -91,5 +91,25 @@ AC_DEFUN([X_AC_DEBUG], [ fi AC_MSG_RESULT([${x_ac_partial_attach=no}]) + + AC_MSG_CHECKING([whether to disable salloc execution in the background]) + AC_ARG_ENABLE( + [salloc-background], + AS_HELP_STRING(--disable-salloc-background,disable salloc execution in the background), + [ case "$enableval" in + yes) x_ac_salloc_background=yes ;; + no) x_ac_salloc_background=no ;; + *) AC_MSG_RESULT([doh!]) + AC_MSG_ERROR([bad value "$enableval" for --disable-salloc-background]) ;; + esac + ] + ) + if test "$x_ac_salloc_background" = no; then + AC_DEFINE(SALLOC_RUN_FOREGROUND, 1, [Define to 1 to require salloc execution in the foreground.]) + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + fi + ] ) diff --git a/config.h.in b/config.h.in index 9964e6289..6fe5b3f51 100644 --- a/config.h.in +++ b/config.h.in @@ -389,6 +389,9 @@ /* Define the project's release. */ #undef RELEASE +/* Define to 1 to require salloc execution in the foreground. */ +#undef SALLOC_RUN_FOREGROUND + /* Define to 1 if sched_getaffinity takes three arguments. */ #undef SCHED_GETAFFINITY_THREE_ARGS diff --git a/configure b/configure index 40f07e42f..e0ab48582 100755 --- a/configure +++ b/configure @@ -1014,6 +1014,7 @@ enable_debug enable_memory_leak_debug enable_front_end enable_partial_attach +enable_salloc_background with_slurmctld_port with_slurmd_port with_slurmdbd_port @@ -1691,6 +1692,8 @@ Optional Features: --enable-front-end enable slurmd operation on a front-end --disable-partial-attach disable debugger partial task attach support + --disable-salloc-background + disable salloc execution in the background --enable-multiple-slurmd enable multiple-slurmd support @@ -7202,13 +7205,13 @@ if test "${lt_cv_nm_interface+set}" = set; then : else lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext - (eval echo "\"\$as_me:7205: $ac_compile\"" >&5) + (eval echo "\"\$as_me:7208: $ac_compile\"" >&5) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&5 - (eval echo "\"\$as_me:7208: $NM \\\"conftest.$ac_objext\\\"\"" >&5) + (eval echo "\"\$as_me:7211: $NM \\\"conftest.$ac_objext\\\"\"" >&5) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&5 - (eval echo "\"\$as_me:7211: output\"" >&5) + (eval echo "\"\$as_me:7214: output\"" >&5) cat conftest.out >&5 if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" @@ -8413,7 +8416,7 @@ ia64-*-hpux*) ;; *-*-irix6*) # Find out which ABI we are using. - echo '#line 8416 "configure"' > conftest.$ac_ext + echo '#line 8419 "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? @@ -10202,11 +10205,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:10205: $lt_compile\"" >&5) + (eval echo "\"\$as_me:10208: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:10209: \$? = $ac_status" >&5 + echo "$as_me:10212: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -10541,11 +10544,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:10544: $lt_compile\"" >&5) + (eval echo "\"\$as_me:10547: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:10548: \$? = $ac_status" >&5 + echo "$as_me:10551: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -10646,11 +10649,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:10649: $lt_compile\"" >&5) + (eval echo "\"\$as_me:10652: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:10653: \$? = $ac_status" >&5 + echo "$as_me:10656: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -10701,11 +10704,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:10704: $lt_compile\"" >&5) + (eval echo "\"\$as_me:10707: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:10708: \$? = $ac_status" >&5 + echo "$as_me:10711: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -13085,7 +13088,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 13088 "configure" +#line 13091 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -13181,7 +13184,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 13184 "configure" +#line 13187 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -15137,11 +15140,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:15140: $lt_compile\"" >&5) + (eval echo "\"\$as_me:15143: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:15144: \$? = $ac_status" >&5 + echo "$as_me:15147: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -15236,11 +15239,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:15239: $lt_compile\"" >&5) + (eval echo "\"\$as_me:15242: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:15243: \$? = $ac_status" >&5 + echo "$as_me:15246: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -15288,11 +15291,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:15291: $lt_compile\"" >&5) + (eval echo "\"\$as_me:15294: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:15295: \$? = $ac_status" >&5 + echo "$as_me:15298: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -19428,6 +19431,33 @@ $as_echo "#define DEBUGGER_PARTIAL_ATTACH 1" >>confdefs.h $as_echo "${x_ac_partial_attach=no}" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to disable salloc execution in the background" >&5 +$as_echo_n "checking whether to disable salloc execution in the background... " >&6; } + # Check whether --enable-salloc-background was given. +if test "${enable_salloc_background+set}" = set; then : + enableval=$enable_salloc_background; case "$enableval" in + yes) x_ac_salloc_background=yes ;; + no) x_ac_salloc_background=no ;; + *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: doh!" >&5 +$as_echo "doh!" >&6; } + as_fn_error $? "bad value \"$enableval\" for --disable-salloc-background" "$LINENO" 5 ;; + esac + + +fi + + if test "$x_ac_salloc_background" = no; then + +$as_echo "#define SALLOC_RUN_FOREGROUND 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + + if test "x$ac_debug" = "xtrue"; then DEBUG_MODULES_TRUE= @@ -20590,7 +20620,7 @@ fi -ac_config_files="$ac_config_files Makefile config.xml auxdir/Makefile contribs/Makefile contribs/pam/Makefile contribs/perlapi/Makefile contribs/perlapi/libslurm/Makefile contribs/perlapi/libslurm/perl/Makefile.PL contribs/perlapi/libslurmdb/Makefile contribs/perlapi/libslurmdb/perl/Makefile.PL contribs/torque/Makefile contribs/phpext/Makefile contribs/phpext/slurm_php/config.m4 contribs/sjobexit/Makefile contribs/slurmdb-direct/Makefile src/Makefile src/api/Makefile src/common/Makefile src/db_api/Makefile src/database/Makefile src/sacct/Makefile src/sacctmgr/Makefile src/sreport/Makefile src/sstat/Makefile src/sshare/Makefile src/salloc/Makefile src/sbatch/Makefile src/sattach/Makefile src/sprio/Makefile src/srun/Makefile src/srun_cr/Makefile src/slurmd/Makefile src/slurmd/slurmd/Makefile src/slurmd/slurmstepd/Makefile src/slurmdbd/Makefile src/slurmctld/Makefile src/sbcast/Makefile src/scontrol/Makefile src/scancel/Makefile src/squeue/Makefile src/sinfo/Makefile src/smap/Makefile src/strigger/Makefile src/sview/Makefile src/plugins/Makefile src/plugins/accounting_storage/Makefile src/plugins/accounting_storage/common/Makefile src/plugins/accounting_storage/filetxt/Makefile src/plugins/accounting_storage/mysql/Makefile src/plugins/accounting_storage/pgsql/Makefile src/plugins/accounting_storage/none/Makefile src/plugins/accounting_storage/slurmdbd/Makefile src/plugins/auth/Makefile src/plugins/auth/authd/Makefile src/plugins/auth/munge/Makefile src/plugins/auth/none/Makefile src/plugins/checkpoint/Makefile src/plugins/checkpoint/aix/Makefile src/plugins/checkpoint/none/Makefile src/plugins/checkpoint/ompi/Makefile src/plugins/checkpoint/xlch/Makefile src/plugins/checkpoint/blcr/Makefile src/plugins/checkpoint/blcr/cr_checkpoint.sh src/plugins/checkpoint/blcr/cr_restart.sh src/plugins/crypto/Makefile src/plugins/crypto/munge/Makefile src/plugins/crypto/openssl/Makefile src/plugins/gres/Makefile src/plugins/gres/gpu/Makefile src/plugins/gres/nic/Makefile src/plugins/jobacct_gather/Makefile src/plugins/jobacct_gather/linux/Makefile src/plugins/jobacct_gather/aix/Makefile src/plugins/jobacct_gather/none/Makefile src/plugins/jobcomp/Makefile src/plugins/jobcomp/filetxt/Makefile src/plugins/jobcomp/none/Makefile src/plugins/jobcomp/script/Makefile src/plugins/jobcomp/mysql/Makefile src/plugins/jobcomp/pgsql/Makefile src/plugins/job_submit/Makefile src/plugins/job_submit/defaults/Makefile src/plugins/job_submit/logging/Makefile src/plugins/job_submit/lua/Makefile src/plugins/job_submit/partition/Makefile src/plugins/preempt/Makefile src/plugins/preempt/none/Makefile src/plugins/preempt/partition_prio/Makefile src/plugins/preempt/qos/Makefile src/plugins/priority/Makefile src/plugins/priority/basic/Makefile src/plugins/priority/multifactor/Makefile src/plugins/proctrack/Makefile src/plugins/proctrack/aix/Makefile src/plugins/proctrack/pgid/Makefile src/plugins/proctrack/linuxproc/Makefile src/plugins/proctrack/rms/Makefile src/plugins/proctrack/sgi_job/Makefile src/plugins/proctrack/cgroup/Makefile src/plugins/proctrack/lua/Makefile src/plugins/sched/Makefile src/plugins/sched/backfill/Makefile src/plugins/sched/builtin/Makefile src/plugins/sched/hold/Makefile src/plugins/sched/wiki/Makefile src/plugins/sched/wiki2/Makefile src/plugins/select/Makefile src/plugins/select/bgq/Makefile src/plugins/select/bluegene/Makefile src/plugins/select/bluegene/block_allocator/Makefile src/plugins/select/bluegene/plugin/Makefile src/plugins/select/cons_res/Makefile src/plugins/select/cray/Makefile src/plugins/select/linear/Makefile src/plugins/switch/Makefile src/plugins/switch/elan/Makefile src/plugins/switch/none/Makefile src/plugins/switch/federation/Makefile src/plugins/mpi/Makefile src/plugins/mpi/mpich1_p4/Makefile src/plugins/mpi/mpich1_shmem/Makefile src/plugins/mpi/mpichgm/Makefile src/plugins/mpi/mpichmx/Makefile src/plugins/mpi/mvapich/Makefile src/plugins/mpi/lam/Makefile src/plugins/mpi/none/Makefile src/plugins/mpi/openmpi/Makefile src/plugins/task/Makefile src/plugins/task/affinity/Makefile src/plugins/task/none/Makefile src/plugins/topology/Makefile src/plugins/topology/3d_torus/Makefile src/plugins/topology/node_rank/Makefile src/plugins/topology/none/Makefile src/plugins/topology/tree/Makefile doc/Makefile doc/man/Makefile doc/html/Makefile doc/html/configurator.html testsuite/Makefile testsuite/expect/Makefile testsuite/slurm_unit/Makefile testsuite/slurm_unit/api/Makefile testsuite/slurm_unit/api/manual/Makefile testsuite/slurm_unit/common/Makefile" +ac_config_files="$ac_config_files Makefile config.xml auxdir/Makefile contribs/Makefile contribs/pam/Makefile contribs/perlapi/Makefile contribs/perlapi/libslurm/Makefile contribs/perlapi/libslurm/perl/Makefile.PL contribs/perlapi/libslurmdb/Makefile contribs/perlapi/libslurmdb/perl/Makefile.PL contribs/torque/Makefile contribs/phpext/Makefile contribs/phpext/slurm_php/config.m4 contribs/sjobexit/Makefile contribs/slurmdb-direct/Makefile src/Makefile src/api/Makefile src/common/Makefile src/db_api/Makefile src/database/Makefile src/sacct/Makefile src/sacctmgr/Makefile src/sreport/Makefile src/sstat/Makefile src/sshare/Makefile src/salloc/Makefile src/sbatch/Makefile src/sattach/Makefile src/sprio/Makefile src/srun/Makefile src/srun_cr/Makefile src/slurmd/Makefile src/slurmd/slurmd/Makefile src/slurmd/slurmstepd/Makefile src/slurmdbd/Makefile src/slurmctld/Makefile src/sbcast/Makefile src/scontrol/Makefile src/scancel/Makefile src/squeue/Makefile src/sinfo/Makefile src/smap/Makefile src/strigger/Makefile src/sview/Makefile src/plugins/Makefile src/plugins/accounting_storage/Makefile src/plugins/accounting_storage/common/Makefile src/plugins/accounting_storage/filetxt/Makefile src/plugins/accounting_storage/mysql/Makefile src/plugins/accounting_storage/pgsql/Makefile src/plugins/accounting_storage/none/Makefile src/plugins/accounting_storage/slurmdbd/Makefile src/plugins/auth/Makefile src/plugins/auth/authd/Makefile src/plugins/auth/munge/Makefile src/plugins/auth/none/Makefile src/plugins/checkpoint/Makefile src/plugins/checkpoint/aix/Makefile src/plugins/checkpoint/none/Makefile src/plugins/checkpoint/ompi/Makefile src/plugins/checkpoint/xlch/Makefile src/plugins/checkpoint/blcr/Makefile src/plugins/checkpoint/blcr/cr_checkpoint.sh src/plugins/checkpoint/blcr/cr_restart.sh src/plugins/crypto/Makefile src/plugins/crypto/munge/Makefile src/plugins/crypto/openssl/Makefile src/plugins/gres/Makefile src/plugins/gres/gpu/Makefile src/plugins/gres/nic/Makefile src/plugins/jobacct_gather/Makefile src/plugins/jobacct_gather/linux/Makefile src/plugins/jobacct_gather/aix/Makefile src/plugins/jobacct_gather/none/Makefile src/plugins/jobcomp/Makefile src/plugins/jobcomp/filetxt/Makefile src/plugins/jobcomp/none/Makefile src/plugins/jobcomp/script/Makefile src/plugins/jobcomp/mysql/Makefile src/plugins/jobcomp/pgsql/Makefile src/plugins/job_submit/Makefile src/plugins/job_submit/cnode/Makefile src/plugins/job_submit/defaults/Makefile src/plugins/job_submit/logging/Makefile src/plugins/job_submit/lua/Makefile src/plugins/job_submit/partition/Makefile src/plugins/preempt/Makefile src/plugins/preempt/none/Makefile src/plugins/preempt/partition_prio/Makefile src/plugins/preempt/qos/Makefile src/plugins/priority/Makefile src/plugins/priority/basic/Makefile src/plugins/priority/multifactor/Makefile src/plugins/proctrack/Makefile src/plugins/proctrack/aix/Makefile src/plugins/proctrack/pgid/Makefile src/plugins/proctrack/linuxproc/Makefile src/plugins/proctrack/rms/Makefile src/plugins/proctrack/sgi_job/Makefile src/plugins/proctrack/cgroup/Makefile src/plugins/proctrack/lua/Makefile src/plugins/sched/Makefile src/plugins/sched/backfill/Makefile src/plugins/sched/builtin/Makefile src/plugins/sched/hold/Makefile src/plugins/sched/wiki/Makefile src/plugins/sched/wiki2/Makefile src/plugins/select/Makefile src/plugins/select/bgq/Makefile src/plugins/select/bluegene/Makefile src/plugins/select/bluegene/block_allocator/Makefile src/plugins/select/bluegene/plugin/Makefile src/plugins/select/cons_res/Makefile src/plugins/select/cray/Makefile src/plugins/select/linear/Makefile src/plugins/switch/Makefile src/plugins/switch/elan/Makefile src/plugins/switch/none/Makefile src/plugins/switch/federation/Makefile src/plugins/mpi/Makefile src/plugins/mpi/mpich1_p4/Makefile src/plugins/mpi/mpich1_shmem/Makefile src/plugins/mpi/mpichgm/Makefile src/plugins/mpi/mpichmx/Makefile src/plugins/mpi/mvapich/Makefile src/plugins/mpi/lam/Makefile src/plugins/mpi/none/Makefile src/plugins/mpi/openmpi/Makefile src/plugins/task/Makefile src/plugins/task/affinity/Makefile src/plugins/task/none/Makefile src/plugins/topology/Makefile src/plugins/topology/3d_torus/Makefile src/plugins/topology/node_rank/Makefile src/plugins/topology/none/Makefile src/plugins/topology/tree/Makefile doc/Makefile doc/man/Makefile doc/html/Makefile doc/html/configurator.html testsuite/Makefile testsuite/expect/Makefile testsuite/slurm_unit/Makefile testsuite/slurm_unit/api/Makefile testsuite/slurm_unit/api/manual/Makefile testsuite/slurm_unit/common/Makefile" cat >confcache <<\_ACEOF @@ -21851,6 +21881,7 @@ do "src/plugins/jobcomp/mysql/Makefile") CONFIG_FILES="$CONFIG_FILES src/plugins/jobcomp/mysql/Makefile" ;; "src/plugins/jobcomp/pgsql/Makefile") CONFIG_FILES="$CONFIG_FILES src/plugins/jobcomp/pgsql/Makefile" ;; "src/plugins/job_submit/Makefile") CONFIG_FILES="$CONFIG_FILES src/plugins/job_submit/Makefile" ;; + "src/plugins/job_submit/cnode/Makefile") CONFIG_FILES="$CONFIG_FILES src/plugins/job_submit/cnode/Makefile" ;; "src/plugins/job_submit/defaults/Makefile") CONFIG_FILES="$CONFIG_FILES src/plugins/job_submit/defaults/Makefile" ;; "src/plugins/job_submit/logging/Makefile") CONFIG_FILES="$CONFIG_FILES src/plugins/job_submit/logging/Makefile" ;; "src/plugins/job_submit/lua/Makefile") CONFIG_FILES="$CONFIG_FILES src/plugins/job_submit/lua/Makefile" ;; diff --git a/configure.ac b/configure.ac index 132cde0cd..5670cf2e7 100644 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -# $Id: configure.ac 21467 2010-11-02 16:14:11Z jette $ +# $Id: configure.ac 22705 2011-03-08 18:43:27Z jette $ # This file is to be processed with autoconf to generate a configure script dnl Prologue @@ -419,6 +419,7 @@ AC_CONFIG_FILES([Makefile src/plugins/jobcomp/mysql/Makefile src/plugins/jobcomp/pgsql/Makefile src/plugins/job_submit/Makefile + src/plugins/job_submit/cnode/Makefile src/plugins/job_submit/defaults/Makefile src/plugins/job_submit/logging/Makefile src/plugins/job_submit/lua/Makefile diff --git a/contribs/perlapi/libslurm/Makefile.am b/contribs/perlapi/libslurm/Makefile.am index 34f26bee0..b0e7e9e6a 100644 --- a/contribs/perlapi/libslurm/Makefile.am +++ b/contribs/perlapi/libslurm/Makefile.am @@ -65,11 +65,13 @@ $(perl_dir)/Makefile: $(perl_dir)/Makefile.PL ${LN_S} -f ${abs_srcdir}/$$f $$f; \ done; \ fi - @cd $(perl_dir) && $(perlpath) Makefile.PL $(PERL_MM_PARAMS) prefix=${prefix} + @cd $(perl_dir) && $(perlpath) Makefile.PL $(PERL_MM_PARAMS) prefix=${prefix} INSTALL_BASE= PERL_MM_OPT= # # Note on linking logic below # +# Install at PREFIX and ignore both INSTALL_BASE and PERL_MM_OPT. Having both +# more than one installation location specification results in a build error. # AIX needs to use LD to link. It can not use gcc. # Suse Linux compiles with gcc, but picks some other compiler to use for linking. # Since some CFLAGS may be incompatible with this other compiler, the build @@ -80,7 +82,7 @@ all-local: $(perl_dir)/Makefile #libslurm if HAVE_AIX @cd $(perl_dir) && \ if [ ! -f Makefile ]; then \ - $(perlpath) Makefile.PL $(PERL_MM_PARAMS) prefix=${prefix}; \ + $(perlpath) Makefile.PL $(PERL_MM_PARAMS) prefix=${prefix} INSTALL_BASE= PERL_MM_OPT= ; \ fi && \ ($(MAKE) CC="$(CC)" CCFLAGS="$(PERL_CFLAGS) -g -static $(CFLAGS)" $(PERL_EXTRA_OPTS) || \ $(MAKE) CC="$(CC)" CCFLAGS="$(PERL_CFLAGS) -g -static $(CFLAGS)" $(PERL_EXTRA_OPTS)) && \ @@ -88,7 +90,7 @@ if HAVE_AIX else @cd $(perl_dir) && \ if [ ! -f Makefile ]; then \ - $(perlpath) Makefile.PL $(PERL_MM_PARAMS) prefix=${prefix}; \ + $(perlpath) Makefile.PL $(PERL_MM_PARAMS) prefix=${prefix} INSTALL_BASE= PERL_MM_OPT= ; \ fi && \ ($(MAKE) CC="$(CC)" LD="$(CC) $(CFLAGS)" CCFLAGS="$(PERL_CFLAGS) -g -static $(CFLAGS)" $(PERL_EXTRA_OPTS) || \ $(MAKE) CC="$(CC)" LD="$(CC) $(CFLAGS)" CCFLAGS="$(PERL_CFLAGS) -g -static $(CFLAGS)" $(PERL_EXTRA_OPTS)) && \ diff --git a/contribs/perlapi/libslurm/Makefile.in b/contribs/perlapi/libslurm/Makefile.in index c91ba2e42..69e452c7b 100644 --- a/contribs/perlapi/libslurm/Makefile.in +++ b/contribs/perlapi/libslurm/Makefile.in @@ -526,11 +526,13 @@ $(perl_dir)/Makefile: $(perl_dir)/Makefile.PL ${LN_S} -f ${abs_srcdir}/$$f $$f; \ done; \ fi - @cd $(perl_dir) && $(perlpath) Makefile.PL $(PERL_MM_PARAMS) prefix=${prefix} + @cd $(perl_dir) && $(perlpath) Makefile.PL $(PERL_MM_PARAMS) prefix=${prefix} INSTALL_BASE= PERL_MM_OPT= # # Note on linking logic below # +# Install at PREFIX and ignore both INSTALL_BASE and PERL_MM_OPT. Having both +# more than one installation location specification results in a build error. # AIX needs to use LD to link. It can not use gcc. # Suse Linux compiles with gcc, but picks some other compiler to use for linking. # Since some CFLAGS may be incompatible with this other compiler, the build @@ -540,14 +542,14 @@ $(perl_dir)/Makefile: $(perl_dir)/Makefile.PL all-local: $(perl_dir)/Makefile #libslurm @HAVE_AIX_TRUE@ @cd $(perl_dir) && \ @HAVE_AIX_TRUE@ if [ ! -f Makefile ]; then \ -@HAVE_AIX_TRUE@ $(perlpath) Makefile.PL $(PERL_MM_PARAMS) prefix=${prefix}; \ +@HAVE_AIX_TRUE@ $(perlpath) Makefile.PL $(PERL_MM_PARAMS) prefix=${prefix} INSTALL_BASE= PERL_MM_OPT= ; \ @HAVE_AIX_TRUE@ fi && \ @HAVE_AIX_TRUE@ ($(MAKE) CC="$(CC)" CCFLAGS="$(PERL_CFLAGS) -g -static $(CFLAGS)" $(PERL_EXTRA_OPTS) || \ @HAVE_AIX_TRUE@ $(MAKE) CC="$(CC)" CCFLAGS="$(PERL_CFLAGS) -g -static $(CFLAGS)" $(PERL_EXTRA_OPTS)) && \ @HAVE_AIX_TRUE@ cd ..; @HAVE_AIX_FALSE@ @cd $(perl_dir) && \ @HAVE_AIX_FALSE@ if [ ! -f Makefile ]; then \ -@HAVE_AIX_FALSE@ $(perlpath) Makefile.PL $(PERL_MM_PARAMS) prefix=${prefix}; \ +@HAVE_AIX_FALSE@ $(perlpath) Makefile.PL $(PERL_MM_PARAMS) prefix=${prefix} INSTALL_BASE= PERL_MM_OPT= ; \ @HAVE_AIX_FALSE@ fi && \ @HAVE_AIX_FALSE@ ($(MAKE) CC="$(CC)" LD="$(CC) $(CFLAGS)" CCFLAGS="$(PERL_CFLAGS) -g -static $(CFLAGS)" $(PERL_EXTRA_OPTS) || \ @HAVE_AIX_FALSE@ $(MAKE) CC="$(CC)" LD="$(CC) $(CFLAGS)" CCFLAGS="$(PERL_CFLAGS) -g -static $(CFLAGS)" $(PERL_EXTRA_OPTS)) && \ diff --git a/contribs/perlapi/libslurmdb/Makefile.am b/contribs/perlapi/libslurmdb/Makefile.am index 2755f7e3b..978d4b542 100644 --- a/contribs/perlapi/libslurmdb/Makefile.am +++ b/contribs/perlapi/libslurmdb/Makefile.am @@ -17,7 +17,7 @@ $(perl_dir)/Makefile: $(perl_dir)/Makefile.PL ${LN_S} -f ${abs_srcdir}/$$f $$f; \ done; \ fi - @cd $(perl_dir) && $(perlpath) Makefile.PL $(PERL_MM_PARAMS) prefix=${prefix} + @cd $(perl_dir) && $(perlpath) Makefile.PL $(PERL_MM_PARAMS) prefix=${prefix} INSTALL_BASE= PERL_MM_OPT= # # Note on linking logic below @@ -32,7 +32,7 @@ all-local: $(perl_dir)/Makefile #libslurmdb if HAVE_AIX @cd $(perl_dir) && \ if [ ! -f Makefile ]; then \ - $(perlpath) Makefile.PL $(PERL_MM_PARAMS) prefix=${prefix}; \ + $(perlpath) Makefile.PL $(PERL_MM_PARAMS) prefix=${prefix} INSTALL_BASE= PERL_MM_OPT=; \ fi && \ ($(MAKE) CC="$(CC)" CCFLAGS="$(PERL_CFLAGS) -g -static $(CFLAGS)" $(PERL_EXTRA_OPTS) || \ $(MAKE) CC="$(CC)" CCFLAGS="$(PERL_CFLAGS) -g -static $(CFLAGS)" $(PERL_EXTRA_OPTS)) && \ @@ -40,7 +40,7 @@ if HAVE_AIX else @cd $(perl_dir) && \ if [ ! -f Makefile ]; then \ - $(perlpath) Makefile.PL $(PERL_MM_PARAMS) prefix=${prefix}; \ + $(perlpath) Makefile.PL $(PERL_MM_PARAMS) prefix=${prefix} INSTALL_BASE= PERL_MM_OPT=; \ fi && \ ($(MAKE) CC="$(CC)" LD="$(CC) $(CFLAGS)" CCFLAGS="$(PERL_CFLAGS) -g -static $(CFLAGS)" $(PERL_EXTRA_OPTS) || \ $(MAKE) CC="$(CC)" LD="$(CC) $(CFLAGS)" CCFLAGS="$(PERL_CFLAGS) -g -static $(CFLAGS)" $(PERL_EXTRA_OPTS)) && \ diff --git a/contribs/perlapi/libslurmdb/Makefile.in b/contribs/perlapi/libslurmdb/Makefile.in index ed3729233..8a13b8392 100644 --- a/contribs/perlapi/libslurmdb/Makefile.in +++ b/contribs/perlapi/libslurmdb/Makefile.in @@ -478,7 +478,7 @@ $(perl_dir)/Makefile: $(perl_dir)/Makefile.PL ${LN_S} -f ${abs_srcdir}/$$f $$f; \ done; \ fi - @cd $(perl_dir) && $(perlpath) Makefile.PL $(PERL_MM_PARAMS) prefix=${prefix} + @cd $(perl_dir) && $(perlpath) Makefile.PL $(PERL_MM_PARAMS) prefix=${prefix} INSTALL_BASE= PERL_MM_OPT= # # Note on linking logic below @@ -492,14 +492,14 @@ $(perl_dir)/Makefile: $(perl_dir)/Makefile.PL all-local: $(perl_dir)/Makefile #libslurmdb @HAVE_AIX_TRUE@ @cd $(perl_dir) && \ @HAVE_AIX_TRUE@ if [ ! -f Makefile ]; then \ -@HAVE_AIX_TRUE@ $(perlpath) Makefile.PL $(PERL_MM_PARAMS) prefix=${prefix}; \ +@HAVE_AIX_TRUE@ $(perlpath) Makefile.PL $(PERL_MM_PARAMS) prefix=${prefix} INSTALL_BASE= PERL_MM_OPT=; \ @HAVE_AIX_TRUE@ fi && \ @HAVE_AIX_TRUE@ ($(MAKE) CC="$(CC)" CCFLAGS="$(PERL_CFLAGS) -g -static $(CFLAGS)" $(PERL_EXTRA_OPTS) || \ @HAVE_AIX_TRUE@ $(MAKE) CC="$(CC)" CCFLAGS="$(PERL_CFLAGS) -g -static $(CFLAGS)" $(PERL_EXTRA_OPTS)) && \ @HAVE_AIX_TRUE@ cd ..; @HAVE_AIX_FALSE@ @cd $(perl_dir) && \ @HAVE_AIX_FALSE@ if [ ! -f Makefile ]; then \ -@HAVE_AIX_FALSE@ $(perlpath) Makefile.PL $(PERL_MM_PARAMS) prefix=${prefix}; \ +@HAVE_AIX_FALSE@ $(perlpath) Makefile.PL $(PERL_MM_PARAMS) prefix=${prefix} INSTALL_BASE= PERL_MM_OPT=; \ @HAVE_AIX_FALSE@ fi && \ @HAVE_AIX_FALSE@ ($(MAKE) CC="$(CC)" LD="$(CC) $(CFLAGS)" CCFLAGS="$(PERL_CFLAGS) -g -static $(CFLAGS)" $(PERL_EXTRA_OPTS) || \ @HAVE_AIX_FALSE@ $(MAKE) CC="$(CC)" LD="$(CC) $(CFLAGS)" CCFLAGS="$(PERL_CFLAGS) -g -static $(CFLAGS)" $(PERL_EXTRA_OPTS)) && \ diff --git a/doc/html/Makefile.am b/doc/html/Makefile.am index 80d5f8110..8128ed38f 100644 --- a/doc/html/Makefile.am +++ b/doc/html/Makefile.am @@ -34,6 +34,7 @@ generated_html = \ moab.html \ mpi_guide.html \ mpiplugins.html \ + multi_cluster.html \ news.html \ overview.html \ platforms.html \ diff --git a/doc/html/Makefile.in b/doc/html/Makefile.in index 93b17c271..8b8d75c88 100644 --- a/doc/html/Makefile.in +++ b/doc/html/Makefile.in @@ -330,6 +330,7 @@ generated_html = \ moab.html \ mpi_guide.html \ mpiplugins.html \ + multi_cluster.html \ news.html \ overview.html \ platforms.html \ diff --git a/doc/html/bluegene.shtml b/doc/html/bluegene.shtml index a0a2a7b51..d9e7d8252 100644 --- a/doc/html/bluegene.shtml +++ b/doc/html/bluegene.shtml @@ -612,6 +612,28 @@ administrators free a bgblock on request (i.e. "<i>sfree --bgblock=<blockname></i>"). Run <i>sfree --help</i> for more information.</p> +<h4>Resource Reservations</h4> + +<p><b>This reservation mechanism for less than an entire midplane is still +under development.</b></p> + +<p>SLURM's advance reservation mechanism is designed to reserve resources +at the level of whole nodes, which on a BlueGene systems would represent +whole midplanes. In order to support advanced reservations with a finer +grained resolution, you can configure one license per c-node on the system +and reserve c-nodes instead of entire midplanes. For example, in slurm.conf +specify something of this sort: "<i>Licenses=cnode*512</i>". Then create an +advanced reservation with a command like this:<br> +"<i>scontrol create reservation licenses="cnode*32" starttime=now duration=30:00 users=joe</i>".</p> + +<p>There is also a job_submit/cnode plugin available for use that will +automatically set a job's license specification to match his c-node request +(i.e. a command like<br> +"<i>sbatch -N32 my.sh</i>" would automatically be translated to<br> +"<i>sbatch -N32 --licenses=cnode*32 my.sh</i>" by the slurmctld daemon. +Enable this plugin in the slurm.conf configuration file with the option +"<i>JobSubmitPlugins=cnode</i>".</p> + <h4>Debugging</h4> <p>All of the testing and debugging guidance provided in diff --git a/doc/html/documentation.shtml b/doc/html/documentation.shtml index 74ea34d84..22bdc38fb 100644 --- a/doc/html/documentation.shtml +++ b/doc/html/documentation.shtml @@ -9,6 +9,7 @@ Also see <a href="publications.html">Publications and Presentations</a>. <li><a href="quickstart.html">Quick Start User Guide</a></li> <li><a href="mpi_guide.html">MPI Use Guide</a></li> <li><a href="mc_support.html">Support for Multi-core/Multi-threaded Architectures</a></li> +<li><a href="multi_cluster.html">Multi-Cluster Operation</a></li> <li><a href="checkpoint_blcr.html">SLURM Checkpoint/Restart with BLCR</a></li> <li><a href="job_exit_code.html">Job Exit Codes</a></li> <li>Specific Systems</li> diff --git a/doc/html/multi_cluster.shtml b/doc/html/multi_cluster.shtml new file mode 100644 index 000000000..d0acca46b --- /dev/null +++ b/doc/html/multi_cluster.shtml @@ -0,0 +1,61 @@ +<!--#include virtual="header.txt"--> + +<h1>Multi-Cluster Operation</h1> + +<p>A cluster is comprised of all the nodes managed by a single slurmctld +daemon. SLURM version 2.2 offers the ability to target commands to other +clusters instead of, or in addition to, the local cluster on which the +command is invoked. When this behavior is enabled, users can submit +jobs to one or many clusters and receive status from those remote +clusters.</p> + +<p>For example:</p> + +<PRE> +juser@dawn> squeue -M dawn,dusk +CLUSTER: dawn +JOBID PARTITION NAME USER ST TIME NODES BP_LIST(REASON) +76897 pdebug myJob juser R 4:10 128 dawn001[8-15] +76898 pdebug myJob juser R 4:10 128 dawn001[16-23] +16899 pdebug myJob juser R 4:10 128 dawn001[24-31] + +CLUSTER: dusk +JOBID PARTITION NAME USER ST TIME NODES BP_LIST(REASON) +11950 pdebug aJob juser R 4:20 128 dusk000[0-15] +11949 pdebug aJob juser R 5:01 128 dusk000[48-63] +11946 pdebug aJob juser R 6:35 128 dusk000[32-47] +11945 pdebug aJob juser R 6:36 128 dusk000[16-31] +</PRE> + +<p>The following SLURM client commands now offer the "-M, --clusters=" +option which provides the ability to communicate to and from a comma +separated list of clusters: +<ol><b>sacct, sbatch, scancel, scontrol, sinfo, smap, sprio, squeue, +sshare,</b> and <b>sstrigger</b></ol> + +<b>salloc, srun,</b> and <b>sstat</b> are cluster specific commands +and do not offer the "-M, --clusters=" option.</p> + +<p>When <b>sbatch</b> is invoked with a cluster list, SLURM will +immediately submit the job to the cluster that offers the earliest +start time subject its queue of pending and running jobs. SLURM will +make no subsequent effort to migrate the job to a different cluster +(from the list) whose resources become available when running jobs +finish before their scheduled end times.</p> + +<h2>Multi-Cluster Configuration</h2> +<p>The multi-cluster functionality requires the use of the slurmDBD. +The AccountingStorageType in the slurm.conf file must be set to the +accounting_storage/slurmdbd plugin and the MUNGE or authentication +keys must be installed to allow each cluster to communicate with the +slurmDBD. Note that MUNGE can be configured to use different keys for +communications within a cluster and across clusters if desired. +See <a href="accounting.html">accounting</a> for details.</p> + +<p>Once configured, SLURM commands specifying the "-M, --clusters=" +option will become active for all of the clusters listed by the +<b>"sacctmgr show clusters"</b> command.</p> + +<p style="text-align:center;">Last modified 14 February 2011</p> + +<!--#include virtual="footer.txt"--> diff --git a/doc/html/reservations.shtml b/doc/html/reservations.shtml index 22365e2ce..67db6686e 100644 --- a/doc/html/reservations.shtml +++ b/doc/html/reservations.shtml @@ -4,8 +4,9 @@ <p>SLURM version 2.0 has the ability to reserve resources for jobs being executed by select users and/or select bank accounts. -A resource reservation identifies the nodes of a resource reservation +A resource reservation identifies the resources in that reservation and a time period during which the reservation is available. +The resouces which can be reserved include nodes and/or licenses. Note that resource reservations are not compatible with SLURM's gang scheduler plugin since the termination time of running jobs is not possible to accurately predict.</p> diff --git a/doc/man/man1/sacct.1 b/doc/man/man1/sacct.1 index f17597673..4c71cd68d 100644 --- a/doc/man/man1/sacct.1 +++ b/doc/man/man1/sacct.1 @@ -29,6 +29,13 @@ identifier (UID) by default. Data for other users can be displayed with the \f3\-\-all\fP, \f3\-\-user\fP, or \f3\-\-uid\fP options. .TP "7" \f3Note: \fP\c +If the AccountingStorageType is set to "accounting_storage/filetxt", +space characters embedded within account names, job names, and step names +will be replaced by underscores. If account names with embedded spaces are +needed, it is recommended that a database type of accounting storage be +configured. +.TP +\f3Note: \fP\c The content's of SLURM's database are maintained in lower case. This may result in some \f3sacct\fP output differing from that of other SLURM commands. .TP diff --git a/doc/man/man1/sacctmgr.1 b/doc/man/man1/sacctmgr.1 index 88c01be6b..c7fc68542 100644 --- a/doc/man/man1/sacctmgr.1 +++ b/doc/man/man1/sacctmgr.1 @@ -1155,16 +1155,29 @@ Only print out the transactions affecting specified accounts. .TP \fIActor\fP=<Specific name the list will display> +Only display transactions done by a certain person. .TP \fIClusters\fP=<comma separated list of cluster names> Only print out the transactions affecting specified clusters. .TP -\fIEndTime\fP=<Date and time where list should end> +\fIEnd\fP=<Date and time of last transaction to return> +Return all transactions before this Date and time. Default is now. .TP -\fIStartTime\fP=<Date and time where list should begin> +\fIStart\fP=<Date and time of first transaction to return> +Return all transactions after this Date and time. Default is epoch. + +Valid time formats for End and Start are... +.sp +HH:MM[:SS] [AM|PM] +.br +MMDD[YY] or MM/DD[/YY] or MM.DD[.YY] +.br +MM/DD[/YY]\-HH:MM[:SS] +.br +YYYY\-MM\-DD[THH:MM[:SS]] .TP \fIUsers\fP=<comma separated list of user names> diff --git a/doc/man/man1/salloc.1 b/doc/man/man1/salloc.1 index eaa68c19e..e8960c8c1 100644 --- a/doc/man/man1/salloc.1 +++ b/doc/man/man1/salloc.1 @@ -21,6 +21,11 @@ section). If no command is specified, then the value of \fBSallocDefaultCommand\fR is not set, then \fBsalloc\fR runs the user's default shell. +NOTE: The salloc logic includes support to save and restore the terminal line +settings and is designed to be executed in the foreground. If you need to +execute salloc in the background, set its standard input to some file, for +example: "salloc \-n16 a.out </dev/null &" + .SH "OPTIONS" .LP @@ -240,6 +245,7 @@ preceded with an optional '0x'. .TP .B sockets Automatically generate masks binding tasks to sockets. +Only the CPUs on the socket which have been allocated to the job will be used. If the number of tasks differs from the number of allocated sockets this can result in sub\-optimal binding. .TP @@ -455,11 +461,24 @@ Multiple license names should be comma separated (e.g. .TP \fB\-m\fR, \fB\-\-distribution\fR= -<\fIblock\fR|\fIcyclic\fR|\fIarbitrary\fR|\fIplane=<options>\fR> -Specify an alternate distribution method for remote processes. In -salloc, this only sets environment variables that will be used by +<\fIblock\fR|\fIcyclic\fR|\fIarbitrary\fR|\fIplane=<options>\fR[:\fIblock\fR|\fIcyclic\fR]> + +Specify alternate distribution methods for remote processes. +In salloc, this only sets environment variables that will be used by subsequent srun requests. +This option controls the assignment of tasks to the nodes on which +resources have been allocated, and the distribution of those resources +to tasks for binding (task affinity). The first distribution +method (before the ":") controls the distribution of resources across +nodes. The optional second distribution method (after the ":") +controls the distribution of resources across sockets within a node. +Note that with select/cons_res, the number of cpus allocated on each +socket and node may be different. Refer to the mc_support.html document +for more information on resource allocation, assignment of tasks to +nodes, and binding of tasks to CPUs. .RS + +First distribution method: .TP .B block The block distribution method will distribute tasks to a node such @@ -478,9 +497,9 @@ nodes each with two cpus. A four\-task cyclic distribution request will distribute those tasks to the nodes with tasks one and four on the first node, task two on the second node, and task three on the third node. -Note that when SelectType is select/cons_res the same number of CPUs -may not be allocated on each node. Distribution will be round\-robin -among all the nodes with CPUs yet to be allocated. +Note that when SelectType is select/cons_res, the same number of CPUs +may not be allocated on each node. Task distribution will be +round\-robin among all the nodes with CPUs yet to be assigned to tasks. Cyclic distribution is the default behavior if the number of tasks is no larger than the number of allocated nodes. .TP @@ -498,12 +517,26 @@ and https://computing.llnl.gov/linux/slurm/dist_plane.html. .TP .B arbitrary -The arbitrary method of distribution will allocate processes in\-order as -listed in file designated by the environment variable SLURM_HOSTFILE. If -this variable is listed it will over ride any other method specified. -If not set the method will default to block. Inside the hostfile must -contain at minimum the number of hosts requested. If requesting tasks -(\-n) your tasks will be laid out on the nodes in the order of the file. +The arbitrary method of distribution will allocate processes in\-order +as listed in file designated by the environment variable +SLURM_HOSTFILE. If this variable is listed it will over ride any +other method specified. If not set the method will default to block. +Inside the hostfile must contain at minimum the number of hosts +requested and be one per line or comma separated. If specifying a +task count (\fB\-n\fR, \fB\-\-ntasks\fR=<\fInumber\fR>), your tasks +will be laid out on the nodes in the order of the file. +.TP + +Second distribution method: +.TP +.B block +The block distribution method will distribute tasks to sockets such +that consecutive tasks share a socket. +.TP +.B cyclic +The cyclic distribution method will distribute tasks to sockets such +that consecutive tasks are distributed over consecutive sockets (in a +round\-robin fashion). .RE .TP @@ -925,7 +958,7 @@ Default from \fIblugene.conf\fR if not set. .TP \fB\-R\fR, \fB\-\-no\-rotate\fR Disables rotation of the job's requested geometry in order to fit an -appropriate partition. +appropriate block. By default the specified geometry can rotate in three dimensions. .TP diff --git a/doc/man/man1/sbatch.1 b/doc/man/man1/sbatch.1 index 4fcb3fd73..c0f324460 100644 --- a/doc/man/man1/sbatch.1 +++ b/doc/man/man1/sbatch.1 @@ -253,6 +253,7 @@ preceded with an optional '0x'. .TP .B sockets Automatically generate masks binding tasks to sockets. +Only the CPUs on the socket which have been allocated to the job will be used. If the number of tasks differs from the number of allocated sockets this can result in sub\-optimal binding. .TP @@ -507,18 +508,31 @@ Multiple license names should be comma separated (e.g. \fB\-M\fR, \fB\-\-clusters\fR=<\fIstring\fR> Clusters to issue commands to. Multiple cluster names may be comma separated. The job will be submitted to the one cluster providing the earliest expected -job initiation time. The default value is the current cluster. A value of -'\fIall\fR' will query to run on all clusters. Note the +job initiation time. The default value is the current cluster. A value of +\(aq\fIall\fR' will query to run on all clusters. Note the \fB\-\-export\fR option to control environment variables exported between clusters. .TP \fB\-m\fR, \fB\-\-distribution\fR= -<\fIblock\fR|\fIcyclic\fR|\fIarbitrary\fR|\fIplane=<options>\fR> -Specify an alternate distribution method for remote processes. In -sbatch, this only sets environment variables that will be used by +<\fIblock\fR|\fIcyclic\fR|\fIarbitrary\fR|\fIplane=<options>\fR[:\fIblock\fR|\fIcyclic\fR]> + +Specify alternate distribution methods for remote processes. +In sbatch, this only sets environment variables that will be used by subsequent srun requests. +This option controls the assignment of tasks to the nodes on which +resources have been allocated, and the distribution of those resources +to tasks for binding (task affinity). The first distribution +method (before the ":") controls the distribution of resources across +nodes. The optional second distribution method (after the ":") +controls the distribution of resources across sockets within a node. +Note that with select/cons_res, the number of cpus allocated on each +socket and node may be different. Refer to the mc_support.html document +for more information on resource allocation, assignment of tasks to +nodes, and binding of tasks to CPUs. .RS + +First distribution method: .TP .B block The block distribution method will distribute tasks to a node such @@ -537,9 +551,9 @@ nodes each with two cpus. A four\-task cyclic distribution request will distribute those tasks to the nodes with tasks one and four on the first node, task two on the second node, and task three on the third node. -Note that when SelectType is select/cons_res the same number of CPUs -may not be allocated on each node. Distribution will be round\-robin -among all the nodes with CPUs yet to be allocated. +Note that when SelectType is select/cons_res, the same number of CPUs +may not be allocated on each node. Task distribution will be +round\-robin among all the nodes with CPUs yet to be assigned to tasks. Cyclic distribution is the default behavior if the number of tasks is no larger than the number of allocated nodes. .TP @@ -557,12 +571,26 @@ and https://computing.llnl.gov/linux/slurm/dist_plane.html. .TP .B arbitrary -The arbitrary method of distribution will allocate processes in\-order as -listed in file designated by the environment variable SLURM_HOSTFILE. If -this variable is listed it will override any other method specified. -If not set the method will default to block. Inside the hostfile must -contain at minimum the number of hosts requested. If requesting tasks -(\-n) your tasks will be laid out on the nodes in the order of the file. +The arbitrary method of distribution will allocate processes in\-order +as listed in file designated by the environment variable +SLURM_HOSTFILE. If this variable is listed it will over ride any +other method specified. If not set the method will default to block. +Inside the hostfile must contain at minimum the number of hosts +requested and be one per line or comma separated. If specifying a +task count (\fB\-n\fR, \fB\-\-ntasks\fR=<\fInumber\fR>), your tasks +will be laid out on the nodes in the order of the file. +.TP + +Second distribution method: +.TP +.B block +The block distribution method will distribute tasks to sockets such +that consecutive tasks share a socket. +.TP +.B cyclic +The cyclic distribution method will distribute tasks to sockets such +that consecutive tasks are distributed over consecutive sockets (in a +round\-robin fashion). .RE .TP @@ -1050,7 +1078,7 @@ Default from \fIblugene.conf\fR if not set. .TP \fB\-R\fR, \fB\-\-no\-rotate\fR Disables rotation of the job's requested geometry in order to fit an -appropriate partition. +appropriate block. By default the specified geometry can rotate in three dimensions. .TP diff --git a/doc/man/man1/scancel.1 b/doc/man/man1/scancel.1 index 143482379..d3b1d0847 100644 --- a/doc/man/man1/scancel.1 +++ b/doc/man/man1/scancel.1 @@ -178,18 +178,16 @@ The location of the SLURM configuration file. If multiple filters are supplied (e.g. \fB\-\-partition\fR and \fB\-\-name\fR) only the jobs satisfying all of the filtering options will be signaled. .LP -If a signal value of "KILL" (the default value) is to be sent to an entire -job, this will result in the job's termination and its resource allocation -being released. +Cancelling a job step will not result in the job being terminated. +The job must be cancelled to release a resource allocation. .LP -Specifying no \-\-signal option will send a SIGTERM and -wait the KillWait duration as defined in the slurm.conf file before sending the -SIGKILL giving time for the running job/step(s) to clean up. To -immediately kill a job, you can specify \-\-signal=KILL which will -bypass the SIGTERM. +To cancel a job, invoke \fBscancel\fR without \-\-signal option. This +will send a SIGTERM to all the job steps, wait the KillWait duration +defined in the slurm.conf file, and then send a SIGKILL. This gives +time for the running job/step(s) to clean up. .LP -Cancelling a job step will not result in a job being terminated. -The job must be cancelled to release a resource allocation. +If a signal value of "KILL" is sent to an entire job, this will cancel +the active job steps but not cancel the job itself. .SH "AUTHORIZATION" diff --git a/doc/man/man1/scontrol.1 b/doc/man/man1/scontrol.1 index 8b24e4654..385c51449 100644 --- a/doc/man/man1/scontrol.1 +++ b/doc/man/man1/scontrol.1 @@ -276,9 +276,9 @@ is restarted or \fBscontrol reconfigure\fR is executed). .TP \fBshow\fP \fIENTITY\fP \fIID\fP Display the state of the specified entity with the specified identification. -\fIENTITY\fP may be \fIconfig\fP, \fIdaemons\fP, \fIjob\fP, \fInode\fP, -\fIpartition\fP, \fIreservation\fP, \fIslurmd\fP, \fIstep\fP, \fItopology\fP, -\fIhostlist\fP or \fIhostnames\fP +\fIENTITY\fP may be \fIaliases\fP, \fIconfig\fP, \fIdaemons\fP, \fIjob\fP, +\fInode\fP, \fIpartition\fP, \fIreservation\fP, \fIslurmd\fP, \fIstep\fP, +\fItopology\fP, \fIhostlist\fP or \fIhostnames\fP (also \fIblock\fP or \fIsubbp\fP on BlueGene systems). \fIID\fP can be used to identify a specific element of the identified entity: the configuration parameter name, job ID, node name, partition name, @@ -289,6 +289,10 @@ If one node name is specified, all switches connected to that node (and their parent switches) will be shown. If more than one node name is specified, only switches that connect to all named nodes will be shown. +\fIaliases\fP will return all \fINodeName\fP values associated to a given +\fINodeHostname\fP (useful to get the list of virtual nodes associated with a +real node in a configuration where multiple slurmd daemons execute on a single +compute node). \fIhostnames\fP takes an optional hostlist expression as input and writes a list of individual host names to standard output (one per line). If no hostlist expression is supplied, the contents of the @@ -357,7 +361,8 @@ updated configuration values to the \fIupdate\fP. Note that while most configuration values can be changed using this command, not all can be changed using this mechanism. In particular, the hardware configuration of a node or the physical addition or removal of nodes from the cluster may only be -accomplished through editing the Slurm configuration file and executing the \fIreconfigure\fP command (described above). +accomplished through editing the Slurm configuration file and executing +the \fIreconfigure\fP command (described above). .TP \fBverbose\fP @@ -368,6 +373,13 @@ This includes time\-stamps on data structures, record counts, etc. \fBversion\fP Display the version number of scontrol being executed. +.TP +\fBwait_job\fP \fIjob_id\fP +Wait until a job andall of its nodes are ready for use or the job has entered +some termination state. This option is particularly useful in the SLURM Prolog +or in the batch script itself if nodes are powered down and restarted +automatically as needed. + .TP \fB!!\fP Repeat the last command executed. @@ -920,22 +932,25 @@ Specification of licenses (or other resources available on all nodes of the cluster) which are to be reserved. License names can be followed by an asterisk and count (the default count is one). -Multiple license names should be comma separated (e.g. -"Licenses=foo*4,bar"). +Multiple license names should be comma separated (e.g. "Licenses=foo*4,bar"). +A new reservation must specify one or more resource to be included: NodeCnt, +Nodes and/or Licenses. .TP \fINodeCnt\fP=<num> -Identify number of nodes to be reserved. A new reservation must specify either -NodeCnt or Nodes. +Identify number of nodes to be reserved. On BlueGene systems, this number represents a cnode (compute node) count and will be rounded up as needed to represent whole nodes (midplanes). +A new reservation must specify one or more resource to be included: NodeCnt, +Nodes and/or Licenses. .TP \fINodes\fP=<name> Identify the node(s) to be reserved. Multiple node names may be specified using simple node range expressions (e.g. "Nodes=lx[10\-20]"). Specify a blank data value to remove all nodes from a reservation: "Nodes=". -A new reservation must specify either NodeCnt or Nodes. +A new reservation must specify one or more resource to be included: NodeCnt, +Nodes and/or Licenses. .TP \fIStartTime\fP=<time_spec> diff --git a/doc/man/man1/squeue.1 b/doc/man/man1/squeue.1 index 5296f3e26..19d48e518 100644 --- a/doc/man/man1/squeue.1 +++ b/doc/man/man1/squeue.1 @@ -173,6 +173,7 @@ Can the nodes allocated to the job be shared with other jobs. \fB%H\fR Number of sockets per node requested by the job. This reports the value of the \fBsrun \-\-sockets\-per\-node\fR option. +When \-\-sockets\-per\-node has not been set, "*" is displayed. (Valid for jobs only) .TP \fB%i\fR @@ -182,6 +183,7 @@ Job or job step id. \fB%I\fR Number of cores per socket requested by the job. This reports the value of the \fBsrun \-\-cores\-per\-socket\fR option. +When \-\-cores\-per\-socket has not been set, "*" is displayed. (Valid for jobs only) .TP \fB%j\fR @@ -191,6 +193,7 @@ Job or job step name. \fB%J\fR Number of threads per core requested by the job. This reports the value of the \fBsrun \-\-threads\-per\-core\fR option. +When \-\-threads\-per\-core has not been set, "*" is displayed. (Valid for jobs only) .TP \fB%k\fR @@ -314,6 +317,7 @@ List of node names explicitly excluded by the job. .TP \fB%z\fR Number of requested sockets, cores, and threads (S:C:T) per node for the job. +When (S:C:T) has not been set, "*" is displayed. (Valid for jobs only) .RE diff --git a/doc/man/man1/srun.1 b/doc/man/man1/srun.1 index e6ac541ed..902cb8097 100644 --- a/doc/man/man1/srun.1 +++ b/doc/man/man1/srun.1 @@ -262,6 +262,7 @@ Not supported unless the entire node is allocated to the job. .TP .B sockets Automatically generate masks binding tasks to sockets. +Only the CPUs on the socket which have been allocated to the job will be used. If the number of tasks differs from the number of allocated sockets this can result in sub\-optimal binding. .TP @@ -299,13 +300,17 @@ unable to execute more than a total of 4 tasks. This option may also be useful to spawn tasks without allocating resources to the job step from the job's allocation when running multiple job steps with the \fB\-\-exclusive\fR option. + \fBWARNING\fR: There are configurations and options interpreted differently by -job and job step requests which can result in inconsistent for this option. +job and job step requests which can result in inconsistencies for this option. For example \fIsrun \-c2 \-\-threads\-per\-core=1 prog\fR may allocate two cores for the job, but if each of those cores contains two threads, the job allocation will include four CPUs. The job step allocation will then launch two threads per CPU for a total of two tasks. +\fBWARNING\fR: When srun is executed from within salloc or sbatch, +there are configurations and options which can result in inconsistent +allocations when \-c has a value greater than \-c on salloc or sbatch. .TP \fB\-d\fR, \fB\-\-dependency\fR=<\fIdependency_list\fR> Defer the start of this job until the specified dependencies have been @@ -513,9 +518,22 @@ Multiple license names should be comma separated (e.g. .TP \fB\-m\fR, \fB\-\-distribution\fR= -<\fIblock\fR|\fIcyclic\fR|\fIarbitrary\fR|\fIplane=<options>\fR> -Specify an alternate distribution method for remote processes. +<\fIblock\fR|\fIcyclic\fR|\fIarbitrary\fR|\fIplane=<options>\fR[:\fIblock\fR|\fIcyclic\fR]> + +Specify alternate distribution methods for remote processes. +This option controls the assignment of tasks to the nodes on which +resources have been allocated, and the distribution of those resources +to tasks for binding (task affinity). The first distribution +method (before the ":") controls the distribution of resources across +nodes. The optional second distribution method (after the ":") +controls the distribution of resources across sockets within a node. +Note that with select/cons_res, the number of cpus allocated on each +socket and node may be different. Refer to the mc_support.html document +for more information on resource allocation, assignment of tasks to +nodes, and binding of tasks to CPUs. .RS + +First distribution method: .TP .B block The block distribution method will distribute tasks to a node such @@ -533,10 +551,10 @@ round\-robin fashion). For example, consider an allocation of three nodes each with two cpus. A four\-task cyclic distribution request will distribute those tasks to the nodes with tasks one and four on the first node, task two on the second node, and task three on the -third node. -Note that when SelectType is select/cons_res the same number of CPUs -may not be allocated on each node. Distribution will be round\-robin -among all the nodes with CPUs yet to be allocated. +third node. +Note that when SelectType is select/cons_res, the same number of CPUs +may not be allocated on each node. Task distribution will be +round\-robin among all the nodes with CPUs yet to be assigned to tasks. Cyclic distribution is the default behavior if the number of tasks is no larger than the number of allocated nodes. .TP @@ -562,6 +580,18 @@ Inside the hostfile must contain at minimum the number of hosts requested and be one per line or comma separated. If specifying a task count (\fB\-n\fR, \fB\-\-ntasks\fR=<\fInumber\fR>), your tasks will be laid out on the nodes in the order of the file. +.TP + +Second distribution method: +.TP +.B block +The block distribution method will distribute tasks to sockets such +that consecutive tasks share a socket. +.TP +.B cyclic +The cyclic distribution method will distribute tasks to sockets such +that consecutive tasks are distributed over consecutive sockets (in a +round\-robin fashion). .RE .TP @@ -1201,7 +1231,7 @@ Default from \fIblugene.conf\fR if not set. .TP \fB\-R\fR, \fB\-\-no\-rotate\fR Disables rotation of the job's requested geometry in order to fit an -appropriate partition. +appropriate block. By default the specified geometry can rotate in three dimensions. .TP @@ -1655,6 +1685,21 @@ count, that count is followed by "(x#)" where "#" is the repetition count. For example, "SLURM_TASKS_PER_NODE=2(x3),1" indicates that the first three nodes will each execute three tasks and the fourth node will execute one task. + +.TP +\fBSLURM_TOPOLOGY_ADDR\fR +This is set only if the system has the topology/tree plugin configured. +The value will be set to the names network switches which may be involved in +the job's communications from the system's top level switch down to the leaf +switch and ending with node name. A period is used to separate each hardware +component name. +.TP +\fBSLURM_TOPOLOGY_ADDR_PATTERN\fR +This is set only if the system has the topology/tree plugin configured. +The value will be set component types listed in \fBSLURM_TOPOLOGY_ADDR\fR. +Each component will be identified as either "switch" or "node". +A period is used to separate each hardware component type. + .TP \fBMPIRUN_NOALLOCATE\fR Do not allocate a block on Blue Gene systems only. @@ -1779,9 +1824,6 @@ the request. The output of each task will be proceeded with its task number. .fi .PP -The output of test.sh would be found in the default output file -"slurm\-42.out." -.PP The srun \fB\-r\fR option is used within a job script to run two job steps on disjoint nodes in the following example. The script is run using allocate mode instead diff --git a/doc/man/man5/slurm.conf.5 b/doc/man/man5/slurm.conf.5 index 6f913f9ae..52641dddc 100644 --- a/doc/man/man5/slurm.conf.5 +++ b/doc/man/man5/slurm.conf.5 @@ -56,17 +56,19 @@ Only used for database type storage plugins, ignored otherwise. .TP \fBAccountingStorageEnforce\fR -This controls what level of enforcement you want on associations when new -jobs are submitted. Valid options are any combination of \fIassociations\fR, \fIlimits\fR, -and \fIwckeys\fR, or \fIall\fR for all things. If limits is set associations is implied. -If wckeys is set both limits and associations are implied along with -TrackWckey being set. By enforcing Associations no new job is allowed to run -unless a corresponding association exists in the system. If limits are -enforced users can be limited by association to how many nodes or how long -jobs can run or other limits. With wckeys enforced jobs will not be scheduled -unless a valid workload characterization key is specified. This value may not -be reset via "scontrol reconfig". It only takes effect upon restart -of the slurmctld daemon. +This controls what level of association\-based enforcement to impose +on job submissions. Valid options are any combination of +\fIassociations\fR, \fIlimits\fR, \fIqos\fR, and \fIwckeys\fR, or +\fIall\fR for all things. If limits, qos, or wckeys are set, +associations will automatically be set. In addition, if wckeys is +set, TrackWCKey will automatically be set. By enforcing Associations +no new job is allowed to run unless a corresponding association exists +in the system. If limits are enforced users can be limited by +association to whatever job size or run time limits are defined. With +qos and/or wckeys enforced jobs will not be scheduled unless a valid +qos and/or workload characterization key is specified. When +\fBAccountingStorageEnforce\fR is changed, a restart of the slurmctld +daemon is required (not just a "scontrol reconfig"). .TP \fBAccountingStorageHost\fR @@ -684,8 +686,8 @@ A comma delimited list of job submission plugins to be used. The specified plugins will be executed in the order listed. These are intended to be site\-specific plugins which can be used to set default job parameters and/or logging events. -Sample plugins available in the distribution include "defaults", "logging", -"lua", and "partition". +Sample plugins available in the distribution include "cnode", "defaults", +"logging", "lua", and "partition". See the SLURM code in "src/plugins/job_submit" and modify the code to satisfy your needs. No job submission plugins are used by default. @@ -1495,7 +1497,7 @@ Sockets are consumable resources. On nodes with multiple cores, each core or thread is counted as a CPU to satisfy a job's resource requirement, but multiple jobs are not allocated resources on the same socket. -Note that jobs requesting one CPU will only be given access to +Note that jobs requesting one CPU will only be allocated that one CPU, but no other job will share the socket. .TP \fBCR_Socket_Memory\fR @@ -1503,7 +1505,7 @@ Memory and sockets are consumable resources. On nodes with multiple cores, each core or thread is counted as a CPU to satisfy a job's resource requirement, but multiple jobs are not allocated resources on the same socket. -Note that jobs requesting one CPU will only be given access to +Note that jobs requesting one CPU will only be allocated that one CPU, but no other job will share the socket. Setting a value for \fBDefMemPerCPU\fR is strongly recommended. .TP @@ -2212,7 +2214,9 @@ Number of logical threads in a single physical core (e.g. "2"). Note that the SLURM can allocate resources to jobs down to the resolution of a core. If your system is configured with more than one thread per core, execution of a different job on each thread -is not supported. +is not supported unless you configure \fBSelectTypeParameters=CR_CPU\fR +plus \fBProcs\fR; do not configure \fBSockets\fR, \fBCoresPerSocket\fR or +\fBThreadsPerCore\fR. A job can execute a one task per thread from within one job step or execute a distinct job step on each of the threads. Note also if you are running with more than 1 thread per core and running diff --git a/slurm.spec b/slurm.spec index 839afc657..7b218e81d 100644 --- a/slurm.spec +++ b/slurm.spec @@ -1,4 +1,4 @@ -# $Id: slurm.spec 22107 2011-01-18 18:33:28Z da $ +# $Id: slurm.spec 22705 2011-03-08 18:43:27Z jette $ # # Note that this package is not relocatable @@ -86,14 +86,14 @@ %endif Name: slurm -Version: 2.2.1 +Version: 2.2.4 Release: 1%{?dist} Summary: Simple Linux Utility for Resource Management License: GPL Group: System Environment/Base -Source: slurm-2.2.1.tar.bz2 +Source: slurm-2.2.4.tar.bz2 BuildRoot: %{_tmppath}/%{name}-%{version}-%{release} URL: https://computing.llnl.gov/linux/slurm/ @@ -368,7 +368,7 @@ Gives the ability for SLURM to use Berkeley Lab Checkpoint/Restart ############################################################################# %prep -%setup -n slurm-2.2.1 +%setup -n slurm-2.2.4 %build %configure --program-prefix=%{?_program_prefix:%{_program_prefix}} \ @@ -602,6 +602,7 @@ rm -rf $RPM_BUILD_ROOT %{_sbindir}/slurm_epilog %{_sbindir}/slurm_prolog %{_sbindir}/sfree +%{_libdir}/slurm/job_submit_cnode.so %config %{_sysconfdir}/bluegene.conf.example %endif ############################################################################# diff --git a/src/api/job_info.c b/src/api/job_info.c index 73fcb69f7..659caad55 100644 --- a/src/api/job_info.c +++ b/src/api/job_info.c @@ -261,20 +261,23 @@ slurm_sprint_job_info ( job_info_t * job_ptr, int one_liner ) line6: snprintf(tmp_line, sizeof(tmp_line), "RunTime="); xstrcat(out, tmp_line); - - run_time = time(NULL); - if (IS_JOB_SUSPENDED(job_ptr)) + if (IS_JOB_PENDING(job_ptr)) + run_time = 0; + else if (IS_JOB_SUSPENDED(job_ptr)) run_time = job_ptr->pre_sus_time; else { - if (!IS_JOB_RUNNING(job_ptr) && (job_ptr->end_time != 0)) - run_time = job_ptr->end_time; + time_t end_time; + if (IS_JOB_RUNNING(job_ptr) || (job_ptr->end_time == 0)) + end_time = time(NULL); + else + end_time = job_ptr->end_time; if (job_ptr->suspend_time) { run_time = (time_t) - (difftime(run_time, job_ptr->suspend_time) + (difftime(end_time, job_ptr->suspend_time) + job_ptr->pre_sus_time); } else run_time = (time_t) - difftime(run_time, job_ptr->start_time); + difftime(end_time, job_ptr->start_time); } secs2time_str(run_time, tmp1, sizeof(tmp1)); sprintf(tmp_line, "%s ", tmp1); diff --git a/src/common/assoc_mgr.c b/src/common/assoc_mgr.c index c0d433d3b..3d21139c0 100644 --- a/src/common/assoc_mgr.c +++ b/src/common/assoc_mgr.c @@ -109,9 +109,9 @@ static int _addto_used_info(slurmdb_association_rec_t *assoc1, return SLURM_SUCCESS; } -static int _clear_used_info(slurmdb_association_rec_t *assoc) +static int _clear_used_assoc_info(slurmdb_association_rec_t *assoc) { - if (!assoc) + if (!assoc || !assoc->usage) return SLURM_ERROR; assoc->usage->grp_used_cpus = 0; @@ -127,6 +127,24 @@ static int _clear_used_info(slurmdb_association_rec_t *assoc) return SLURM_SUCCESS; } +static int _clear_used_qos_info(slurmdb_qos_rec_t *qos) +{ + if (!qos || !qos->usage) + return SLURM_ERROR; + + qos->usage->grp_used_cpus = 0; + qos->usage->grp_used_nodes = 0; + + qos->usage->grp_used_jobs = 0; + qos->usage->grp_used_submit_jobs = 0; + /* do not reset usage_raw or grp_used_wall. + * if you need to reset it do it + * else where since sometimes we call this and do not want + * shares reset */ + + return SLURM_SUCCESS; +} + /* Locks should be in place before calling this. */ static int _change_user_name(slurmdb_user_rec_t *user) { @@ -2452,7 +2470,7 @@ extern int assoc_mgr_update_assocs(slurmdb_update_object_t *update) changed we could have different usage */ if (!object->user) { - _clear_used_info(object); + _clear_used_assoc_info(object); object->usage->usage_raw = 0; object->usage->grp_used_wall = 0; } @@ -3091,18 +3109,27 @@ extern void assoc_mgr_clear_used_info(void) { ListIterator itr = NULL; slurmdb_association_rec_t * found_assoc = NULL; + slurmdb_qos_rec_t * found_qos = NULL; assoc_mgr_lock_t locks = { WRITE_LOCK, NO_LOCK, - NO_LOCK, NO_LOCK, NO_LOCK }; - - if (!assoc_mgr_association_list) - return; + WRITE_LOCK, NO_LOCK, NO_LOCK }; assoc_mgr_lock(&locks); - itr = list_iterator_create(assoc_mgr_association_list); - while ((found_assoc = list_next(itr))) { - _clear_used_info(found_assoc); + if (assoc_mgr_association_list) { + itr = list_iterator_create(assoc_mgr_association_list); + while ((found_assoc = list_next(itr))) { + _clear_used_assoc_info(found_assoc); + } + list_iterator_destroy(itr); } - list_iterator_destroy(itr); + + if (assoc_mgr_qos_list) { + itr = list_iterator_create(assoc_mgr_qos_list); + while ((found_qos = list_next(itr))) { + _clear_used_qos_info(found_qos); + } + list_iterator_destroy(itr); + } + assoc_mgr_unlock(&locks); } diff --git a/src/common/env.c b/src/common/env.c index 3688392b3..8963a639a 100644 --- a/src/common/env.c +++ b/src/common/env.c @@ -94,7 +94,8 @@ static int _setup_particulars(uint32_t cluster_flags, SELECT_JOBDATA_BLOCK_ID, &bg_part_id); if (bg_part_id) { - if (cluster_flags & CLUSTER_FLAG_BGL) { + /* check to see if this is a HTC block or not. */ + if (cluster_flags & CLUSTER_FLAG_BGP) { uint16_t conn_type = (uint16_t)NO_VAL; select_g_select_jobinfo_get( @@ -102,6 +103,8 @@ static int _setup_particulars(uint32_t cluster_flags, SELECT_JOBDATA_CONN_TYPE, &conn_type); if (conn_type > SELECT_SMALL) { + /* SUBMIT_POOL over rides + HTC_SUBMIT_POOL */ setenvf(dest, "SUBMIT_POOL", "%s", bg_part_id); } diff --git a/src/common/pack.c b/src/common/pack.c index 14dd6fc36..b50ad75a7 100644 --- a/src/common/pack.c +++ b/src/common/pack.c @@ -210,16 +210,16 @@ int unpack_time(time_t * valp, Buf buffer) */ void packdouble(double val, Buf buffer) { - double nl1 = (val * FLOAT_MULT) + .5; /* the .5 is here to - round off. We have - found on systems - going out more than - 15 decimals will - mess things up so - this is here to - correct it. */ - uint64_t nl = HTON_uint64(nl1); - + uint64_t nl; + union { + double d; + uint64_t u; + } uval; + + /* The 0.5 is here to round off. We have found on systems going out + * more than 15 decimals will mess things up, but this corrects it. */ + uval.d = (val * FLOAT_MULT); + nl = HTON_uint64(uval.u); if (remaining_buf(buffer) < sizeof(nl)) { if (buffer->size > (MAX_BUF_SIZE - BUF_SIZE)) { error("packdouble: buffer size too large"); @@ -231,7 +231,6 @@ void packdouble(double val, Buf buffer) memcpy(&buffer->head[buffer->processed], &nl, sizeof(nl)); buffer->processed += sizeof(nl); - } /* @@ -242,13 +241,20 @@ void packdouble(double val, Buf buffer) int unpackdouble(double *valp, Buf buffer) { uint64_t nl; + union { + double d; + uint64_t u; + } uval; + if (remaining_buf(buffer) < sizeof(nl)) return SLURM_ERROR; memcpy(&nl, &buffer->head[buffer->processed], sizeof(nl)); - - *valp = (double)NTOH_uint64(nl) / (double)FLOAT_MULT; buffer->processed += sizeof(nl); + + uval.u = NTOH_uint64(nl); + *valp = uval.d / FLOAT_MULT; + return SLURM_SUCCESS; } diff --git a/src/common/parse_config.c b/src/common/parse_config.c index 51b026cc5..0b821605c 100644 --- a/src/common/parse_config.c +++ b/src/common/parse_config.c @@ -43,12 +43,14 @@ # include "config.h" #endif +#include <ctype.h> +#include <regex.h> #include <string.h> +#include <sys/stat.h> #include <sys/types.h> -#include <regex.h> #include <stdint.h> #include <stdlib.h> -#include <ctype.h> +#include <unistd.h> /* #include "src/common/slurm_protocol_defs.h" */ #include "src/common/log.h" @@ -843,6 +845,7 @@ int s_p_parse_file(s_p_hashtbl_t *hashtbl, uint32_t *hash_val, char *filename) int line_number; int merged_lines; int inc_rc; + struct stat stat_buf; if (!filename) { error("s_p_parse_file: No filename given."); @@ -850,7 +853,14 @@ int s_p_parse_file(s_p_hashtbl_t *hashtbl, uint32_t *hash_val, char *filename) } _keyvalue_regex_init(); - + if (stat(filename, &stat_buf) < 0) { + info("s_p_parse_file: unable to status file \"%s\"", filename); + return SLURM_ERROR; + } + if (stat_buf.st_size == 0) { + info("s_p_parse_file: file \"%s\" is empty", filename); + return SLURM_SUCCESS; + } f = fopen(filename, "r"); if (f == NULL) { error("s_p_parse_file: unable to read \"%s\": %m", diff --git a/src/common/parse_time.c b/src/common/parse_time.c index 5fecb9a42..24cddb06e 100644 --- a/src/common/parse_time.c +++ b/src/common/parse_time.c @@ -548,7 +548,7 @@ slurm_make_time_str (time_t *time, char *string, int size) struct tm time_tm; localtime_r(time, &time_tm); - if ( *time == (time_t) 0 ) { + if ((*time == (time_t) 0) || (*time == (time_t) INFINITE)) { snprintf(string, size, "Unknown"); } else { #ifdef USE_ISO_8601 diff --git a/src/common/read_config.c b/src/common/read_config.c index f37bb3e46..1bafc7fb1 100644 --- a/src/common/read_config.c +++ b/src/common/read_config.c @@ -1200,6 +1200,43 @@ extern char *slurm_conf_get_nodename(const char *node_hostname) return NULL; } +/* + * slurm_conf_get_aliases - Return all the nodes NodeName value + * associated to a given NodeHostname (usefull in case of multiple-slurmd + * to get the list of virtual nodes associated with a real node) + * + * NOTE: Call xfree() to release returned value's memory. + * NOTE: Caller must NOT be holding slurm_conf_lock(). + */ +extern char *slurm_conf_get_aliases(const char *node_hostname) +{ + int idx; + names_ll_t *p; + char *aliases = NULL; + char *s = NULL; + + slurm_conf_lock(); + _init_slurmd_nodehash(); + idx = _get_hash_idx(node_hostname); + + p = host_to_node_hashtbl[idx]; + while (p) { + if (strcmp(p->hostname, node_hostname) == 0) { + if ( aliases == NULL ) + aliases = xstrdup(p->alias); + else { + s = xstrdup_printf("%s %s",aliases,p->alias); + xfree(aliases); + aliases = s; + } + } + p = p->next_hostname; + } + slurm_conf_unlock(); + + return aliases; +} + /* * slurm_conf_get_nodeaddr - Return the NodeAddr for given NodeHostname * @@ -2278,6 +2315,8 @@ _validate_and_set_defaults(slurm_ctl_conf_t *conf, s_p_hashtbl_t *hashtbl) if (conf->preempt_mode == PREEMPT_MODE_SUSPEND) fatal("PreemptMode=SUSPEND requires GANG too"); xfree(temp_str); + } else { + conf->preempt_mode = PREEMPT_MODE_OFF; } if (!s_p_get_string(&conf->preempt_type, "PreemptType", hashtbl)) conf->preempt_type = xstrdup(DEFAULT_PREEMPT_TYPE); diff --git a/src/common/read_config.h b/src/common/read_config.h index ffe660bcc..aff22aa52 100644 --- a/src/common/read_config.h +++ b/src/common/read_config.h @@ -299,6 +299,16 @@ extern char *slurm_conf_get_hostname(const char *node_name); */ extern char *slurm_conf_get_nodename(const char *node_hostname); +/* + * slurm_conf_get_aliases - Return all the nodes NodeName value + * associated to a given NodeHostname (usefull in case of multiple-slurmd + * to get the list of virtual nodes associated with a real node) + * + * NOTE: Call xfree() to release returned value's memory. + * NOTE: Caller must NOT be holding slurm_conf_lock(). + */ +extern char *slurm_conf_get_aliases(const char *node_hostname); + /* * slurm_conf_get_nodeaddr - Return the NodeAddr for given NodeHostname * diff --git a/src/common/slurm_protocol_api.c b/src/common/slurm_protocol_api.c index c812dce83..6bc9a12d8 100644 --- a/src/common/slurm_protocol_api.c +++ b/src/common/slurm_protocol_api.c @@ -1947,7 +1947,7 @@ slurm_fd_t slurm_open_controller_conn(slurm_addr_t *addr) myproto->primary_controller.sin_port; } - for (retry=0; retry<4; retry++) { + for (retry=0; retry<slurm_get_msg_timeout(); retry++) { if (retry) sleep(1); if (working_cluster_rec) { diff --git a/src/common/slurm_protocol_defs.c b/src/common/slurm_protocol_defs.c index 76dabb094..5cb6025cd 100644 --- a/src/common/slurm_protocol_defs.c +++ b/src/common/slurm_protocol_defs.c @@ -142,37 +142,19 @@ extern void slurm_destroy_uint32_ptr(void *object) /* here to add \\ to all \" in a string this needs to be xfreed later */ extern char *slurm_add_slash_to_quotes(char *str) { - int i=0, start=0; - char *fixed = NULL; - - if(!str) + char *dup, *copy = NULL; + int len = 0; + if(!str || !(len = strlen(str))) return NULL; - while(str[i]) { - if((str[i] == '"')) { - char *tmp = xstrndup(str+start, i-start); - xstrfmtcat(fixed, "%s\\\"", tmp); - xfree(tmp); - start = i+1; - } - - if((str[i] == '\'')) { - char *tmp = xstrndup(str+start, i-start); - xstrfmtcat(fixed, "%s\\\'", tmp); - xfree(tmp); - start = i+1; - } - - i++; - } - - if((i-start) > 0) { - char *tmp = xstrndup(str+start, i-start); - xstrcat(fixed, tmp); - xfree(tmp); - } + /* make a buffer 2 times the size just to be safe */ + copy = dup = xmalloc((2 * len) + 1); + if (copy) + do if (*str == '\'' || *str == '"') + *dup++ = '\\'; + while ((*dup++ = *str++)); - return fixed; + return copy; } /* returns number of objects added to list */ diff --git a/src/common/slurm_step_layout.c b/src/common/slurm_step_layout.c index f2a4c2676..a5c3211a5 100644 --- a/src/common/slurm_step_layout.c +++ b/src/common/slurm_step_layout.c @@ -646,24 +646,26 @@ static int _task_layout_cyclic(slurm_step_layout_t *step_layout, /* * The plane distribution results in a block cyclic of block size * "plane_size". - * The plane distribution does not do any workload balancing and - * just use the user specified blocksize: "plane_size". - * This distribution does not take the hardware (number of CPUs - * per node) into account when computing the number of tasks per - * hosts. + * To effectively deal with heterogeneous nodes, we fake a cyclic + * distribution to figure out how many tasks go on each node and + * then make the assignments of task numbers to nodes using the + * user-specified plane size. * For example: - * plane_size = 2 - * node Node0 Node1 - * -- -- -- -- - * task distribution: 0 1 2 3 - * 4 5 6 7 - * 8 9 10 11 - * 12 13 14 15 etc. + * plane_size = 2, #tasks = 6, #nodes = 3 + * + * Node#: Node0 Node1 Node2 + * ----- ----- ----- + * #of allocated CPUs: 4 1 1 + * + * task distribution: 0 1 2 3 + * 4 5 */ static int _task_layout_plane(slurm_step_layout_t *step_layout, uint16_t *cpus) { int i, j, k, taskid = 0; + bool over_subscribe = false; + uint32_t cur_task[step_layout->node_cnt]; debug3("_task_layout_plane plane_size %u node_cnt %u task_cnt %u", step_layout->plane_size, @@ -675,22 +677,39 @@ static int _task_layout_plane(slurm_step_layout_t *step_layout, if (step_layout->tasks == NULL) return SLURM_ERROR; - for (i=0; i<step_layout->node_cnt; i++) { - step_layout->tids[i] = xmalloc(sizeof(uint32_t) - * step_layout->task_cnt); + /* figure out how many tasks go to each node */ + for (j=0; taskid<step_layout->task_cnt; j++) { /* cycle counter */ + bool space_remaining = false; + for (i=0; ((i<step_layout->node_cnt) + && (taskid<step_layout->task_cnt)); i++) { + if ((j<cpus[i]) || over_subscribe) { + taskid++; + step_layout->tasks[i]++; + if ((j+1) < cpus[i]) + space_remaining = true; + } + } + if (!space_remaining) + over_subscribe = true; } + /* now distribute the tasks */ taskid = 0; + for (i=0; i < step_layout->node_cnt; i++) { + step_layout->tids[i] = xmalloc(sizeof(uint32_t) + * step_layout->tasks[i]); + cur_task[i] = 0; + } for (j=0; taskid<step_layout->task_cnt; j++) { /* cycle counter */ for (i=0; ((i<step_layout->node_cnt) && (taskid<step_layout->task_cnt)); i++) { /* assign a block of 'plane_size' tasks to this node */ for (k=0; ((k<step_layout->plane_size) - && (taskid<step_layout->task_cnt)); k++) { - step_layout->tids[i][step_layout->tasks[i]] = - taskid; + && (cur_task[i] < step_layout->tasks[i]) + && (taskid < step_layout->task_cnt)); k++) { + step_layout->tids[i][cur_task[i]] = taskid; taskid++; - step_layout->tasks[i]++; + cur_task[i]++; } } } diff --git a/src/plugins/accounting_storage/filetxt/accounting_storage_filetxt.c b/src/plugins/accounting_storage/filetxt/accounting_storage_filetxt.c index 65d95c93d..7fb49e101 100644 --- a/src/plugins/accounting_storage/filetxt/accounting_storage_filetxt.c +++ b/src/plugins/accounting_storage/filetxt/accounting_storage_filetxt.c @@ -170,6 +170,26 @@ static int _print_record(struct job_record *job_ptr, return rc; } +/* Make a copy of in_string replacing spaces with underscores. + * Use xfree to release returned memory */ +static char *_safe_dup(char *in_string) +{ + int i; + char *out_string; + + if (in_string && in_string[0]) { + out_string = xstrdup(in_string); + for (i = 0; out_string[i]; i++) { + if (isspace(out_string[i])) + out_string[i]='_'; + } + } else { + out_string = xstrdup("(null)"); + } + + return out_string; +} + /* * init() is called when the plugin is loaded, before any other functions * are called. Put global initialization here. @@ -527,8 +547,7 @@ extern int clusteracct_storage_p_cluster_cpus(void *db_conn, extern int jobacct_storage_p_job_start(void *db_conn, struct job_record *job_ptr) { - int i, - rc=SLURM_SUCCESS; + int rc = SLURM_SUCCESS; char buf[BUFFER_SIZE], *account, *nodes; char *jname = NULL; long priority; @@ -553,25 +572,19 @@ extern int jobacct_storage_p_job_start(void *db_conn, -1L : (long) job_ptr->priority; if (job_ptr->name && job_ptr->name[0]) { - jname = xstrdup(job_ptr->name); - for (i=0; jname[i]; i++) - if (isspace(jname[i])) - jname[i]='_'; + jname = _safe_dup(job_ptr->name); } else { jname = xstrdup("allocation"); track_steps = 1; } - if (job_ptr->account && job_ptr->account[0]) - account = job_ptr->account; - else - account = "(null)"; + account= _safe_dup(job_ptr->account); if (job_ptr->nodes && job_ptr->nodes[0]) nodes = job_ptr->nodes; else nodes = "(null)"; - if(job_ptr->batch_flag) + if (job_ptr->batch_flag) track_steps = 1; job_ptr->requid = -1; /* force to -1 for stats to know this @@ -584,7 +597,7 @@ extern int jobacct_storage_p_job_start(void *db_conn, nodes, account); rc = _print_record(job_ptr, job_ptr->start_time, buf); - + xfree(account); xfree(jname); return rc; } @@ -639,13 +652,13 @@ extern int jobacct_storage_p_step_start(void *db_conn, struct step_record *step_ptr) { char buf[BUFFER_SIZE]; - int cpus = 0; + int cpus = 0, rc; char node_list[BUFFER_SIZE]; #ifdef HAVE_BG char *ionodes = NULL; #endif float float_tmp = 0; - char *account; + char *account, *step_name; if(!storage_init) { debug("jobacct init was not called or it failed"); @@ -678,10 +691,8 @@ extern int jobacct_storage_p_step_start(void *db_conn, step_ptr->step_layout->node_list); } #endif - if (step_ptr->job_ptr->account && step_ptr->job_ptr->account[0]) - account = step_ptr->job_ptr->account; - else - account = "(null)"; + account = _safe_dup(step_ptr->job_ptr->account); + step_name = _safe_dup(step_ptr->name); step_ptr->job_ptr->requid = -1; /* force to -1 for stats to know this * hasn't been set yet */ @@ -697,9 +708,9 @@ extern int jobacct_storage_p_step_start(void *db_conn, 0, /* total cputime seconds */ 0, /* total cputime seconds */ 0, /* user seconds */ - 0,/* user microseconds */ + 0, /* user microseconds */ 0, /* system seconds */ - 0,/* system microsecs */ + 0, /* system microsecs */ 0, /* max rss */ 0, /* max ixrss */ 0, /* max idrss */ @@ -726,7 +737,7 @@ extern int jobacct_storage_p_step_start(void *db_conn, 0, /* min cpu */ 0, /* min cpu task */ float_tmp, /* ave cpu */ - step_ptr->name, /* step exe name */ + step_name, /* step exe name */ node_list, /* name of nodes step running on */ 0, /* max vsize node */ 0, /* max rss node */ @@ -735,7 +746,10 @@ extern int jobacct_storage_p_step_start(void *db_conn, account, step_ptr->job_ptr->requid); /* requester user id */ - return _print_record(step_ptr->job_ptr, step_ptr->start_time, buf); + rc = _print_record(step_ptr->job_ptr, step_ptr->start_time, buf); + xfree(account); + xfree(step_name); + return rc; } /* @@ -748,7 +762,7 @@ extern int jobacct_storage_p_step_complete(void *db_conn, time_t now; int elapsed; int comp_status; - int cpus = 0; + int cpus = 0, rc; char node_list[BUFFER_SIZE]; struct jobacctinfo *jobacct = (struct jobacctinfo *)step_ptr->jobacct; struct jobacctinfo dummy_jobacct; @@ -758,7 +772,7 @@ extern int jobacct_storage_p_step_complete(void *db_conn, float ave_vsize = 0, ave_rss = 0, ave_pages = 0; float ave_cpu = 0; uint32_t ave_cpu2 = 0; - char *account; + char *account, *step_name; uint32_t exit_code; if(!storage_init) { @@ -829,10 +843,8 @@ extern int jobacct_storage_p_step_complete(void *db_conn, ave_cpu2 = jobacct->min_cpu; } - if (step_ptr->job_ptr->account && step_ptr->job_ptr->account[0]) - account = step_ptr->job_ptr->account; - else - account = "(null)"; + account = _safe_dup(step_ptr->job_ptr->account); + step_name = _safe_dup(step_ptr->name); snprintf(buf, BUFFER_SIZE, _jobstep_format, JOB_STEP, @@ -878,7 +890,7 @@ extern int jobacct_storage_p_step_complete(void *db_conn, ave_cpu2, /* min cpu */ jobacct->min_cpu_id.taskid, /* min cpu node */ ave_cpu, /* ave cpu */ - step_ptr->name, /* step exe name */ + step_name, /* step exe name */ node_list, /* name of nodes step running on */ jobacct->max_vsize_id.nodeid, /* max vsize task */ jobacct->max_rss_id.nodeid, /* max rss task */ @@ -887,7 +899,10 @@ extern int jobacct_storage_p_step_complete(void *db_conn, account, step_ptr->job_ptr->requid); /* requester user id */ - return _print_record(step_ptr->job_ptr, now, buf); + rc = _print_record(step_ptr->job_ptr, now, buf); + xfree(account); + xfree(step_name); + return rc; } /* diff --git a/src/plugins/accounting_storage/mysql/accounting_storage_mysql.c b/src/plugins/accounting_storage/mysql/accounting_storage_mysql.c index 4ae38fd2e..1d923fc6e 100644 --- a/src/plugins/accounting_storage/mysql/accounting_storage_mysql.c +++ b/src/plugins/accounting_storage/mysql/accounting_storage_mysql.c @@ -73,6 +73,11 @@ char *slurmctld_cluster_name = NULL; #endif List as_mysql_cluster_list = NULL; +/* This total list is only used for converting things, so no + need to keep it upto date even though it lives until the + end of the life of the slurmdbd. +*/ +List as_mysql_total_cluster_list = NULL; pthread_mutex_t as_mysql_cluster_list_lock = PTHREAD_MUTEX_INITIALIZER; /* @@ -150,7 +155,7 @@ enum { extern int acct_storage_p_close_connection(mysql_conn_t **mysql_conn); -static List _get_cluster_names(mysql_conn_t *mysql_conn) +static List _get_cluster_names(mysql_conn_t *mysql_conn, bool with_deleted) { MYSQL_RES *result = NULL; MYSQL_ROW row; @@ -158,8 +163,10 @@ static List _get_cluster_names(mysql_conn_t *mysql_conn) char *cluster_name = NULL; bool found = 0; - char *query = xstrdup_printf("select name from %s where deleted=0", - cluster_table); + char *query = xstrdup_printf("select name from %s", cluster_table); + + if (!with_deleted) + xstrcat(query, " where deleted=0"); if (!(result = mysql_db_query_ret(mysql_conn, query, 0))) { xfree(query); @@ -612,15 +619,28 @@ static int _as_mysql_acct_check_tables(mysql_conn_t *mysql_conn) return SLURM_ERROR; slurm_mutex_lock(&as_mysql_cluster_list_lock); - if (!(as_mysql_cluster_list = _get_cluster_names(mysql_conn))) { + if (!(as_mysql_cluster_list = _get_cluster_names(mysql_conn, 0))) { error("issue getting contents of %s", cluster_table); slurm_mutex_unlock(&as_mysql_cluster_list_lock); return SLURM_ERROR; } + /* This total list is only used for converting things, so no + need to keep it upto date even though it lives until the + end of the life of the slurmdbd. + */ + if (!(as_mysql_total_cluster_list = + _get_cluster_names(mysql_conn, 1))) { + error("issue getting total contents of %s", cluster_table); + slurm_mutex_unlock(&as_mysql_cluster_list_lock); + return SLURM_ERROR; + } + /* might as well do all the cluster centric tables inside this - * lock */ - itr = list_iterator_create(as_mysql_cluster_list); + * lock. We need to do this on all the clusters deleted or + * other wise just to make sure everything is kept up to + * date. */ + itr = list_iterator_create(as_mysql_total_cluster_list); while ((cluster_name = list_next(itr))) { if ((rc = create_cluster_tables(mysql_conn, cluster_name)) != SLURM_SUCCESS) @@ -1307,20 +1327,59 @@ extern int remove_cluster_tables(mysql_conn_t *mysql_conn, char *cluster_name) extern int setup_association_limits(slurmdb_association_rec_t *assoc, char **cols, char **vals, char **extra, qos_level_t qos_level, - bool get_fs) + bool for_add) { if (!assoc) return SLURM_ERROR; - if ((int32_t)assoc->shares_raw >= 0) { - xstrcat(*cols, ", shares"); - xstrfmtcat(*vals, ", %u", assoc->shares_raw); - xstrfmtcat(*extra, ", shares=%u", assoc->shares_raw); - } else if ((assoc->shares_raw == INFINITE) || get_fs) { + if (for_add) { + /* If we are adding we should make sure we don't get + old reside sitting around from a former life. + */ + if (assoc->shares_raw == NO_VAL) + assoc->shares_raw = INFINITE; + if (assoc->grp_cpu_mins == (uint64_t)NO_VAL) + assoc->grp_cpu_mins = (uint64_t)INFINITE; + if (assoc->grp_cpu_run_mins == (uint64_t)NO_VAL) + assoc->grp_cpu_run_mins = (uint64_t)INFINITE; + if (assoc->grp_cpus == NO_VAL) + assoc->grp_cpus = INFINITE; + if (assoc->grp_jobs == NO_VAL) + assoc->grp_jobs = INFINITE; + if (assoc->grp_nodes == NO_VAL) + assoc->grp_nodes = INFINITE; + if (assoc->grp_submit_jobs == NO_VAL) + assoc->grp_submit_jobs = INFINITE; + if (assoc->grp_wall == NO_VAL) + assoc->grp_wall = INFINITE; + if (assoc->max_cpu_mins_pj == (uint64_t)NO_VAL) + assoc->max_cpu_mins_pj = (uint64_t)INFINITE; + if (assoc->max_cpu_run_mins == (uint64_t)NO_VAL) + assoc->max_cpu_run_mins = (uint64_t)INFINITE; + if (assoc->max_cpus_pj == NO_VAL) + assoc->max_cpus_pj = INFINITE; + if (assoc->max_jobs == NO_VAL) + assoc->max_jobs = INFINITE; + if (assoc->max_nodes_pj == NO_VAL) + assoc->max_nodes_pj = INFINITE; + if (assoc->max_submit_jobs == NO_VAL) + assoc->max_submit_jobs = INFINITE; + if (assoc->max_wall_pj == NO_VAL) + assoc->max_wall_pj = INFINITE; + if (assoc->def_qos_id == NO_VAL) + assoc->def_qos_id = INFINITE; + } + + if (assoc->shares_raw == INFINITE) { xstrcat(*cols, ", shares"); xstrcat(*vals, ", 1"); xstrcat(*extra, ", shares=1"); assoc->shares_raw = 1; + } else if ((assoc->shares_raw != NO_VAL) + && (int32_t)assoc->shares_raw >= 0) { + xstrcat(*cols, ", shares"); + xstrfmtcat(*vals, ", %u", assoc->shares_raw); + xstrfmtcat(*extra, ", shares=%u", assoc->shares_raw); } if (assoc->grp_cpu_mins == (uint64_t)INFINITE) { @@ -1336,6 +1395,19 @@ extern int setup_association_limits(slurmdb_association_rec_t *assoc, assoc->grp_cpu_mins); } + if (assoc->grp_cpu_run_mins == (uint64_t)INFINITE) { + xstrcat(*cols, ", grp_cpu_run_mins"); + xstrcat(*vals, ", NULL"); + xstrcat(*extra, ", grp_cpu_run_mins=NULL"); + } else if ((assoc->grp_cpu_run_mins != (uint64_t)NO_VAL) + && ((int64_t)assoc->grp_cpu_run_mins >= 0)) { + xstrcat(*cols, ", grp_cpu_run_mins"); + xstrfmtcat(*vals, ", %"PRIu64"", + assoc->grp_cpu_run_mins); + xstrfmtcat(*extra, ", grp_cpu_run_mins=%"PRIu64"", + assoc->grp_cpu_run_mins); + } + if (assoc->grp_cpus == INFINITE) { xstrcat(*cols, ", grp_cpus"); xstrcat(*vals, ", NULL"); @@ -1415,6 +1487,19 @@ extern int setup_association_limits(slurmdb_association_rec_t *assoc, assoc->max_cpu_mins_pj); } + if (assoc->max_cpu_run_mins == (uint64_t)INFINITE) { + xstrcat(*cols, ", max_cpu_run_mins"); + xstrcat(*vals, ", NULL"); + xstrcat(*extra, ", max_cpu_run_mins=NULL"); + } else if ((assoc->max_cpu_run_mins != (uint64_t)NO_VAL) + && ((int64_t)assoc->max_cpu_run_mins >= 0)) { + xstrcat(*cols, ", max_cpu_run_mins"); + xstrfmtcat(*vals, ", %"PRIu64"", + assoc->max_cpu_run_mins); + xstrfmtcat(*extra, ", max_cpu_run_mins=%"PRIu64"", + assoc->max_cpu_run_mins); + } + if (assoc->max_cpus_pj == INFINITE) { xstrcat(*cols, ", max_cpus_pj"); xstrcat(*vals, ", NULL"); @@ -2018,6 +2103,10 @@ extern int fini ( void ) list_destroy(as_mysql_cluster_list); as_mysql_cluster_list = NULL; } + if (as_mysql_total_cluster_list) { + list_destroy(as_mysql_total_cluster_list); + as_mysql_total_cluster_list = NULL; + } slurm_mutex_unlock(&as_mysql_cluster_list_lock); slurm_mutex_destroy(&as_mysql_cluster_list_lock); destroy_mysql_db_info(mysql_db_info); diff --git a/src/plugins/accounting_storage/mysql/accounting_storage_mysql.h b/src/plugins/accounting_storage/mysql/accounting_storage_mysql.h index a82305a6b..962211080 100644 --- a/src/plugins/accounting_storage/mysql/accounting_storage_mysql.h +++ b/src/plugins/accounting_storage/mysql/accounting_storage_mysql.h @@ -98,6 +98,7 @@ extern char *wckey_table; * go off of. */ extern List as_mysql_cluster_list; +extern List as_mysql_total_cluster_list; extern pthread_mutex_t as_mysql_cluster_list_lock; @@ -117,7 +118,7 @@ extern int remove_cluster_tables(mysql_conn_t *mysql_conn, char *cluster_name); extern int setup_association_limits(slurmdb_association_rec_t *assoc, char **cols, char **vals, char **extra, qos_level_t qos_level, - bool get_fs); + bool for_add); extern int modify_common(mysql_conn_t *mysql_conn, uint16_t type, time_t now, diff --git a/src/plugins/accounting_storage/mysql/as_mysql_assoc.c b/src/plugins/accounting_storage/mysql/as_mysql_assoc.c index f6ec84908..04d986bb7 100644 --- a/src/plugins/accounting_storage/mysql/as_mysql_assoc.c +++ b/src/plugins/accounting_storage/mysql/as_mysql_assoc.c @@ -1370,7 +1370,8 @@ static int _process_modify_assoc_results(mysql_conn_t *mysql_conn, slurmdb_association_rec_t *assoc, slurmdb_user_rec_t *user, char *cluster_name, char *sent_vals, - bool is_admin, List ret_list) + bool is_admin, bool same_user, + List ret_list) { ListIterator itr = NULL; MYSQL_ROW row; @@ -1414,7 +1415,11 @@ static int _process_modify_assoc_results(mysql_conn_t *mysql_conn, if (row[MASSOC_PACCT][0]) account = row[MASSOC_PACCT]; - if (!is_admin) { + /* If this is the same user all has been done + previously to make sure the user is only changing + things they are allowed to change. + */ + if (!is_admin && !same_user) { slurmdb_coord_rec_t *coord = NULL; if (!user->coord_accts) { // This should never @@ -2954,7 +2959,8 @@ extern List as_mysql_modify_assocs(mysql_conn_t *mysql_conn, uint32_t uid, int rc = SLURM_SUCCESS; char *object = NULL; char *vals = NULL, *extra = NULL, *query = NULL; - int set = 0, i = 0, is_admin=0; + int set = 0, i = 0; + bool is_admin=0, same_user=0; MYSQL_RES *result = NULL; slurmdb_user_rec_t user; char *tmp_char1=NULL, *tmp_char2=NULL; @@ -2982,12 +2988,20 @@ extern List as_mysql_modify_assocs(mysql_conn_t *mysql_conn, uint32_t uid, name = list_peek(assoc_cond->user_list); if ((uid_from_string (name, &pw_uid) >= 0) && (pw_uid == uid)) { + uint16_t is_def = assoc->is_def; + uint32_t def_qos_id = assoc->def_qos_id; /* Make sure they aren't trying to - change something else and then set - this association as a default. + change something they aren't + allowed to. Currently they are + only allowed to change the default + account, and default QOS. */ slurmdb_init_association_rec(assoc, 1); - assoc->is_def = 1; + + assoc->is_def = is_def; + assoc->def_qos_id = def_qos_id; + same_user = 1; + goto is_same_user; } } @@ -3068,7 +3082,8 @@ is_same_user: xfree(query); rc = _process_modify_assoc_results(mysql_conn, result, assoc, &user, cluster_name, vals, - is_admin, ret_list); + is_admin, same_user, + ret_list); mysql_free_result(result); if ((rc == ESLURM_INVALID_PARENT_ACCOUNT) diff --git a/src/plugins/accounting_storage/mysql/as_mysql_cluster.c b/src/plugins/accounting_storage/mysql/as_mysql_cluster.c index 2db13a672..4fea7753f 100644 --- a/src/plugins/accounting_storage/mysql/as_mysql_cluster.c +++ b/src/plugins/accounting_storage/mysql/as_mysql_cluster.c @@ -3,7 +3,7 @@ ***************************************************************************** * * Copyright (C) 2004-2007 The Regents of the University of California. - * Copyright (C) 2008-2010 Lawrence Livermore National Security. + * Copyright (C) 2008-2011 Lawrence Livermore National Security. * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). * Written by Danny Auble <da@llnl.gov> * diff --git a/src/plugins/accounting_storage/mysql/as_mysql_convert.c b/src/plugins/accounting_storage/mysql/as_mysql_convert.c index e442ea215..d9398b150 100644 --- a/src/plugins/accounting_storage/mysql/as_mysql_convert.c +++ b/src/plugins/accounting_storage/mysql/as_mysql_convert.c @@ -1208,7 +1208,7 @@ extern int as_mysql_convert_tables(mysql_conn_t *mysql_conn) slurm_mutex_lock(&as_mysql_cluster_list_lock); /* now convert to new form */ - itr = list_iterator_create(as_mysql_cluster_list); + itr = list_iterator_create(as_mysql_total_cluster_list); while ((cluster_name = list_next(itr))) { pthread_t convert_tid; pthread_attr_t convert_attr; @@ -1380,7 +1380,7 @@ extern int as_mysql_convert_tables(mysql_conn_t *mysql_conn) } } - while (converted < list_count(as_mysql_cluster_list)) { + while (converted < list_count(as_mysql_total_cluster_list)) { pthread_cond_wait(&converted_cond, &converted_lock); debug2("Got %d converted", converted); } diff --git a/src/plugins/accounting_storage/mysql/as_mysql_job.c b/src/plugins/accounting_storage/mysql/as_mysql_job.c index 27c745a0b..d4b4e8d1e 100644 --- a/src/plugins/accounting_storage/mysql/as_mysql_job.c +++ b/src/plugins/accounting_storage/mysql/as_mysql_job.c @@ -350,9 +350,9 @@ extern int as_mysql_job_start(mysql_conn_t *mysql_conn, no_rollup_change: if (job_ptr->name && job_ptr->name[0]) - jname = job_ptr->name; + jname = slurm_add_slash_to_quotes(job_ptr->name); else { - jname = "allocation"; + jname = xstrdup("allocation"); track_steps = 1; } @@ -519,6 +519,7 @@ no_rollup_change: } xfree(block_id); + xfree(jname); xfree(query); /* now we will reset all the steps */ @@ -740,7 +741,7 @@ extern int as_mysql_step_start(mysql_conn_t *mysql_conn, int cpus = 0, tasks = 0, nodes = 0, task_dist = 0; int rc=SLURM_SUCCESS; char node_list[BUFFER_SIZE]; - char *node_inx = NULL; + char *node_inx = NULL, *step_name = NULL; time_t start_time, submit_time; #ifdef HAVE_BG @@ -846,6 +847,8 @@ extern int as_mysql_step_start(mysql_conn_t *mysql_conn, } } + step_name = slurm_add_slash_to_quotes(step_ptr->name); + /* we want to print a -1 for the requid so leave it a %d */ /* The stepid could be -2 so use %d not %u */ @@ -862,7 +865,7 @@ extern int as_mysql_step_start(mysql_conn_t *mysql_conn, mysql_conn->cluster_name, step_table, step_ptr->job_ptr->db_index, step_ptr->step_id, - (int)start_time, step_ptr->name, + (int)start_time, step_name, JOB_RUNNING, cpus, nodes, tasks, node_list, node_inx, task_dist, cpus, nodes, tasks, JOB_RUNNING, node_list, node_inx, task_dist); @@ -870,6 +873,7 @@ extern int as_mysql_step_start(mysql_conn_t *mysql_conn, mysql_conn->conn, THIS_FILE, __LINE__, query); rc = mysql_db_query(mysql_conn, query); xfree(query); + xfree(step_name); return rc; } diff --git a/src/plugins/accounting_storage/mysql/as_mysql_qos.c b/src/plugins/accounting_storage/mysql/as_mysql_qos.c index 5db0f6552..2434d2916 100644 --- a/src/plugins/accounting_storage/mysql/as_mysql_qos.c +++ b/src/plugins/accounting_storage/mysql/as_mysql_qos.c @@ -78,11 +78,56 @@ static int _preemption_loop(mysql_conn_t *mysql_conn, int begin_qosid, static int _setup_qos_limits(slurmdb_qos_rec_t *qos, char **cols, char **vals, - char **extra, char **added_preempt) + char **extra, char **added_preempt, + bool for_add) { if (!qos) return SLURM_ERROR; + if (for_add) { + /* If we are adding we should make sure we don't get + old reside sitting around from a former life. + */ + if (!qos->description) + qos->description = xstrdup(""); + if (qos->flags & QOS_FLAG_NOTSET) + qos->flags = 0; + if (qos->grp_cpu_mins == (uint64_t)NO_VAL) + qos->grp_cpu_mins = (uint64_t)INFINITE; + if (qos->grp_cpu_run_mins == (uint64_t)NO_VAL) + qos->grp_cpu_run_mins = (uint64_t)INFINITE; + if (qos->grp_cpus == NO_VAL) + qos->grp_cpus = INFINITE; + if (qos->grp_jobs == NO_VAL) + qos->grp_jobs = INFINITE; + if (qos->grp_nodes == NO_VAL) + qos->grp_nodes = INFINITE; + if (qos->grp_submit_jobs == NO_VAL) + qos->grp_submit_jobs = INFINITE; + if (qos->grp_wall == NO_VAL) + qos->grp_wall = INFINITE; + if (qos->max_cpu_mins_pj == (uint64_t)NO_VAL) + qos->max_cpu_mins_pj = (uint64_t)INFINITE; + if (qos->grp_cpu_run_mins == (uint64_t)NO_VAL) + qos->grp_cpu_run_mins = (uint64_t)INFINITE; + if (qos->max_cpus_pj == NO_VAL) + qos->max_cpus_pj = INFINITE; + if (qos->max_jobs_pu == NO_VAL) + qos->max_jobs_pu = INFINITE; + if (qos->max_nodes_pj == NO_VAL) + qos->max_nodes_pj = INFINITE; + if (qos->max_submit_jobs_pu == NO_VAL) + qos->max_submit_jobs_pu = INFINITE; + if (qos->max_wall_pj == NO_VAL) + qos->max_wall_pj = INFINITE; + if (qos->preempt_mode == (uint16_t)NO_VAL) + qos->preempt_mode = (uint16_t)INFINITE; + if (qos->usage_factor == (double)NO_VAL) + qos->usage_factor = (double)INFINITE; + if (qos->usage_thres == (double)NO_VAL) + qos->usage_thres = (double)INFINITE; + } + if (qos->description) { xstrcat(*cols, ", description"); xstrfmtcat(*vals, ", '%s'", qos->description); @@ -321,7 +366,7 @@ static int _setup_qos_limits(slurmdb_qos_rec_t *qos, xfree(preempt_val); } - if ((qos->usage_factor != (int16_t)NO_VAL) + if ((qos->preempt_mode != (uint16_t)NO_VAL) && ((int16_t)qos->preempt_mode >= 0)) { qos->preempt_mode &= (~PREEMPT_MODE_GANG); xstrcat(*cols, ", preempt_mode"); @@ -396,7 +441,8 @@ extern int as_mysql_add_qos(mysql_conn_t *mysql_conn, uint32_t uid, now, now, object->name); xstrfmtcat(extra, ", mod_time=%ld", now); - _setup_qos_limits(object, &cols, &vals, &extra, &added_preempt); + _setup_qos_limits(object, &cols, &vals, + &extra, &added_preempt, 1); if (added_preempt) { object->preempt_bitstr = bit_alloc(g_qos_count); bit_unfmt(object->preempt_bitstr, added_preempt+1); @@ -545,7 +591,8 @@ extern List as_mysql_modify_qos(mysql_conn_t *mysql_conn, uint32_t uid, xstrcat(extra, ")"); } - _setup_qos_limits(qos, &tmp_char1, &tmp_char2, &vals, &added_preempt); + _setup_qos_limits(qos, &tmp_char1, &tmp_char2, + &vals, &added_preempt, 0); if (added_preempt) { preempt_bitstr = bit_alloc(g_qos_count); bit_unfmt(preempt_bitstr, added_preempt+1); diff --git a/src/plugins/accounting_storage/mysql/as_mysql_txn.c b/src/plugins/accounting_storage/mysql/as_mysql_txn.c index 5e2310c71..dcc838c89 100644 --- a/src/plugins/accounting_storage/mysql/as_mysql_txn.c +++ b/src/plugins/accounting_storage/mysql/as_mysql_txn.c @@ -135,7 +135,6 @@ extern List as_mysql_get_txn(mysql_conn_t *mysql_conn, uid_t uid, set = 1; } list_iterator_destroy(itr); - xstrcat(assoc_extra, ")"); xstrcat(name_extra, ")"); use_cluster_list = txn_cond->cluster_list; } diff --git a/src/plugins/job_submit/Makefile.am b/src/plugins/job_submit/Makefile.am index 848a499b8..d3e3e4f56 100644 --- a/src/plugins/job_submit/Makefile.am +++ b/src/plugins/job_submit/Makefile.am @@ -4,4 +4,4 @@ if HAVE_LUA LUA = lua endif -SUBDIRS = defaults logging $(LUA) partition +SUBDIRS = cnode defaults logging $(LUA) partition diff --git a/src/plugins/job_submit/Makefile.in b/src/plugins/job_submit/Makefile.in index 37b49885e..96825d9cd 100644 --- a/src/plugins/job_submit/Makefile.in +++ b/src/plugins/job_submit/Makefile.in @@ -96,7 +96,7 @@ AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ distdir ETAGS = etags CTAGS = ctags -DIST_SUBDIRS = defaults logging lua partition +DIST_SUBDIRS = cnode defaults logging lua partition DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ @@ -315,7 +315,7 @@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ @HAVE_LUA_TRUE@LUA = lua -SUBDIRS = defaults logging $(LUA) partition +SUBDIRS = cnode defaults logging $(LUA) partition all: all-recursive .SUFFIXES: diff --git a/src/plugins/job_submit/cnode/Makefile.am b/src/plugins/job_submit/cnode/Makefile.am new file mode 100644 index 000000000..871cbe518 --- /dev/null +++ b/src/plugins/job_submit/cnode/Makefile.am @@ -0,0 +1,13 @@ +# Makefile for job_submit/cnode plugin + +AUTOMAKE_OPTIONS = foreign + +PLUGIN_FLAGS = -module -avoid-version --export-dynamic + +INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src/common + +pkglib_LTLIBRARIES = job_submit_cnode.la + +# Job submit cnode plugin. +job_submit_cnode_la_SOURCES = job_submit_cnode.c +job_submit_cnode_la_LDFLAGS = $(SO_LDFLAGS) $(PLUGIN_FLAGS) diff --git a/src/plugins/job_submit/cnode/Makefile.in b/src/plugins/job_submit/cnode/Makefile.in new file mode 100644 index 000000000..33101d4ba --- /dev/null +++ b/src/plugins/job_submit/cnode/Makefile.in @@ -0,0 +1,637 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Makefile for job_submit/cnode plugin + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = src/plugins/job_submit/cnode +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/auxdir/acx_pthread.m4 \ + $(top_srcdir)/auxdir/libtool.m4 \ + $(top_srcdir)/auxdir/ltoptions.m4 \ + $(top_srcdir)/auxdir/ltsugar.m4 \ + $(top_srcdir)/auxdir/ltversion.m4 \ + $(top_srcdir)/auxdir/lt~obsolete.m4 \ + $(top_srcdir)/auxdir/slurm.m4 \ + $(top_srcdir)/auxdir/x_ac__system_configuration.m4 \ + $(top_srcdir)/auxdir/x_ac_affinity.m4 \ + $(top_srcdir)/auxdir/x_ac_aix.m4 \ + $(top_srcdir)/auxdir/x_ac_blcr.m4 \ + $(top_srcdir)/auxdir/x_ac_bluegene.m4 \ + $(top_srcdir)/auxdir/x_ac_cflags.m4 \ + $(top_srcdir)/auxdir/x_ac_cray.m4 \ + $(top_srcdir)/auxdir/x_ac_databases.m4 \ + $(top_srcdir)/auxdir/x_ac_debug.m4 \ + $(top_srcdir)/auxdir/x_ac_elan.m4 \ + $(top_srcdir)/auxdir/x_ac_env.m4 \ + $(top_srcdir)/auxdir/x_ac_federation.m4 \ + $(top_srcdir)/auxdir/x_ac_gpl_licensed.m4 \ + $(top_srcdir)/auxdir/x_ac_hwloc.m4 \ + $(top_srcdir)/auxdir/x_ac_iso.m4 \ + $(top_srcdir)/auxdir/x_ac_lua.m4 \ + $(top_srcdir)/auxdir/x_ac_munge.m4 \ + $(top_srcdir)/auxdir/x_ac_ncurses.m4 \ + $(top_srcdir)/auxdir/x_ac_pam.m4 \ + $(top_srcdir)/auxdir/x_ac_printf_null.m4 \ + $(top_srcdir)/auxdir/x_ac_ptrace.m4 \ + $(top_srcdir)/auxdir/x_ac_readline.m4 \ + $(top_srcdir)/auxdir/x_ac_setpgrp.m4 \ + $(top_srcdir)/auxdir/x_ac_setproctitle.m4 \ + $(top_srcdir)/auxdir/x_ac_sgi_job.m4 \ + $(top_srcdir)/auxdir/x_ac_slurm_ssl.m4 \ + $(top_srcdir)/auxdir/x_ac_sun_const.m4 \ + $(top_srcdir)/auxdir/x_ac_xcpu.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h $(top_builddir)/slurm/slurm.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__installdirs = "$(DESTDIR)$(pkglibdir)" +LTLIBRARIES = $(pkglib_LTLIBRARIES) +job_submit_cnode_la_LIBADD = +am_job_submit_cnode_la_OBJECTS = job_submit_cnode.lo +job_submit_cnode_la_OBJECTS = $(am_job_submit_cnode_la_OBJECTS) +job_submit_cnode_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(job_submit_cnode_la_LDFLAGS) $(LDFLAGS) -o $@ +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) -I$(top_builddir)/slurm +depcomp = $(SHELL) $(top_srcdir)/auxdir/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(job_submit_cnode_la_SOURCES) +DIST_SOURCES = $(job_submit_cnode_la_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTHD_CFLAGS = @AUTHD_CFLAGS@ +AUTHD_LIBS = @AUTHD_LIBS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BGL_LOADED = @BGL_LOADED@ +BG_INCLUDES = @BG_INCLUDES@ +BLCR_CPPFLAGS = @BLCR_CPPFLAGS@ +BLCR_HOME = @BLCR_HOME@ +BLCR_LDFLAGS = @BLCR_LDFLAGS@ +BLCR_LIBS = @BLCR_LIBS@ +BLUEGENE_LOADED = @BLUEGENE_LOADED@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CMD_LDFLAGS = @CMD_LDFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ELAN_LIBS = @ELAN_LIBS@ +EXEEXT = @EXEEXT@ +FEDERATION_LDFLAGS = @FEDERATION_LDFLAGS@ +FGREP = @FGREP@ +GREP = @GREP@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +HAVEMYSQLCONFIG = @HAVEMYSQLCONFIG@ +HAVEPGCONFIG = @HAVEPGCONFIG@ +HAVE_AIX = @HAVE_AIX@ +HAVE_ELAN = @HAVE_ELAN@ +HAVE_FEDERATION = @HAVE_FEDERATION@ +HAVE_OPENSSL = @HAVE_OPENSSL@ +HAVE_SOME_CURSES = @HAVE_SOME_CURSES@ +HWLOC_CPPFLAGS = @HWLOC_CPPFLAGS@ +HWLOC_LDFLAGS = @HWLOC_LDFLAGS@ +HWLOC_LIBS = @HWLOC_LIBS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIB_LDFLAGS = @LIB_LDFLAGS@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MUNGE_CPPFLAGS = @MUNGE_CPPFLAGS@ +MUNGE_LDFLAGS = @MUNGE_LDFLAGS@ +MUNGE_LIBS = @MUNGE_LIBS@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +NCURSES = @NCURSES@ +NM = @NM@ +NMEDIT = @NMEDIT@ +NUMA_LIBS = @NUMA_LIBS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PAM_DIR = @PAM_DIR@ +PAM_LIBS = @PAM_LIBS@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PGSQL_CFLAGS = @PGSQL_CFLAGS@ +PGSQL_LIBS = @PGSQL_LIBS@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PROCTRACKDIR = @PROCTRACKDIR@ +PROJECT = @PROJECT@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +RANLIB = @RANLIB@ +READLINE_LIBS = @READLINE_LIBS@ +RELEASE = @RELEASE@ +SED = @SED@ +SEMAPHORE_LIBS = @SEMAPHORE_LIBS@ +SEMAPHORE_SOURCES = @SEMAPHORE_SOURCES@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SLURMCTLD_PORT = @SLURMCTLD_PORT@ +SLURMCTLD_PORT_COUNT = @SLURMCTLD_PORT_COUNT@ +SLURMDBD_PORT = @SLURMDBD_PORT@ +SLURMD_PORT = @SLURMD_PORT@ +SLURM_API_AGE = @SLURM_API_AGE@ +SLURM_API_CURRENT = @SLURM_API_CURRENT@ +SLURM_API_MAJOR = @SLURM_API_MAJOR@ +SLURM_API_REVISION = @SLURM_API_REVISION@ +SLURM_API_VERSION = @SLURM_API_VERSION@ +SLURM_MAJOR = @SLURM_MAJOR@ +SLURM_MICRO = @SLURM_MICRO@ +SLURM_MINOR = @SLURM_MINOR@ +SLURM_PREFIX = @SLURM_PREFIX@ +SLURM_VERSION_NUMBER = @SLURM_VERSION_NUMBER@ +SLURM_VERSION_STRING = @SLURM_VERSION_STRING@ +SO_LDFLAGS = @SO_LDFLAGS@ +SSL_CPPFLAGS = @SSL_CPPFLAGS@ +SSL_LDFLAGS = @SSL_LDFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +UTIL_LIBS = @UTIL_LIBS@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +lt_ECHO = @lt_ECHO@ +lua_CFLAGS = @lua_CFLAGS@ +lua_LIBS = @lua_LIBS@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AUTOMAKE_OPTIONS = foreign +PLUGIN_FLAGS = -module -avoid-version --export-dynamic +INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src/common +pkglib_LTLIBRARIES = job_submit_cnode.la + +# Job submit cnode plugin. +job_submit_cnode_la_SOURCES = job_submit_cnode.c +job_submit_cnode_la_LDFLAGS = $(SO_LDFLAGS) $(PLUGIN_FLAGS) +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/plugins/job_submit/cnode/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/plugins/job_submit/cnode/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(pkglibdir)" || $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" + @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ + } + +uninstall-pkglibLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ + done + +clean-pkglibLTLIBRARIES: + -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) + @list='$(pkglib_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +job_submit_cnode.la: $(job_submit_cnode_la_OBJECTS) $(job_submit_cnode_la_DEPENDENCIES) + $(job_submit_cnode_la_LINK) -rpath $(pkglibdir) $(job_submit_cnode_la_OBJECTS) $(job_submit_cnode_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/job_submit_cnode.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(pkglibdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-pkglibLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-pkglibLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pkglibLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-pkglibLTLIBRARIES ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-pkglibLTLIBRARIES \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-pkglibLTLIBRARIES + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/plugins/job_submit/cnode/job_submit_cnode.c b/src/plugins/job_submit/cnode/job_submit_cnode.c new file mode 100644 index 000000000..ed48f3ae2 --- /dev/null +++ b/src/plugins/job_submit/cnode/job_submit_cnode.c @@ -0,0 +1,184 @@ +/*****************************************************************************\ + * job_submit_cnode.c - Set a job's cnode license count equal to the number + * of cnode required (BlueGene compute nodes). This mechanism can be used to + * manage resource reservations of less than a full midplane. + * + * NOTE: In order to use this, configure licenses on the computer named + * "cnode" and having a count equal to all cnodes on the system. + ***************************************************************************** + * Copyright (C) 2011 Lawrence Livermore National Security. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Morris Jette <jette1@llnl.gov> + * CODE-OCEC-09-009. All rights reserved. + * + * This file is part of SLURM, a resource management program. + * For details, see <https://computing.llnl.gov/linux/slurm/>. + * Please also read the included file: DISCLAIMER. + * + * SLURM is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * In addition, as a special exception, the copyright holders give permission + * to link the code of portions of this program with the OpenSSL library under + * certain conditions as described in each individual source file, and + * distribute linked combinations including the two. You must obey the GNU + * General Public License in all respects for all of the code used other than + * OpenSSL. If you modify file(s) with this exception, you may extend this + * exception to your version of the file(s), but you are not obligated to do + * so. If you do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source files in + * the program, then also delete it here. + * + * SLURM is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along + * with SLURM; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +\*****************************************************************************/ + +#if HAVE_CONFIG_H +# include "config.h" +# if STDC_HEADERS +# include <string.h> +# endif +# if HAVE_SYS_TYPES_H +# include <sys/types.h> +# endif /* HAVE_SYS_TYPES_H */ +# if HAVE_UNISTD_H +# include <unistd.h> +# endif +# if HAVE_INTTYPES_H +# include <inttypes.h> +# else /* ! HAVE_INTTYPES_H */ +# if HAVE_STDINT_H +# include <stdint.h> +# endif +# endif /* HAVE_INTTYPES_H */ +#else /* ! HAVE_CONFIG_H */ +# include <sys/types.h> +# include <unistd.h> +# include <stdint.h> +# include <string.h> +#endif /* HAVE_CONFIG_H */ + +#include <stdio.h> + +#include <slurm/slurm_errno.h> +#include "src/common/slurm_xlator.h" +#include "src/slurmctld/slurmctld.h" + +/* Define the minimum number of cnodes which can be allocated on a system. + * This is hardware and configuration dependent. More work is needed here. */ +#ifndef MIN_CNODES +#define MIN_CNODES 32 +#endif + +/* + * These variables are required by the generic plugin interface. If they + * are not found in the plugin, the plugin loader will ignore it. + * + * plugin_name - a string giving a human-readable description of the + * plugin. There is no maximum length, but the symbol must refer to + * a valid string. + * + * plugin_type - a string suggesting the type of the plugin or its + * applicability to a particular form of data or method of data handling. + * If the low-level plugin API is used, the contents of this string are + * unimportant and may be anything. SLURM uses the higher-level plugin + * interface which requires this string to be of the form + * + * <application>/<method> + * + * where <application> is a description of the intended application of + * the plugin (e.g., "auth" for SLURM authentication) and <method> is a + * description of how this plugin satisfies that application. SLURM will + * only load authentication plugins if the plugin_type string has a prefix + * of "auth/". + * + * plugin_version - specifies the version number of the plugin. + * min_plug_version - specifies the minumum version number of incoming + * messages that this plugin can accept + */ +const char plugin_name[] = "Job submit cnode plugin"; +const char plugin_type[] = "job_submit/cnode"; +const uint32_t plugin_version = 100; +const uint32_t min_plug_version = 100; + +static void _rebuild_licenses(char **license_ptr, uint32_t cnode_cnt) +{ + char *sep = "", *save_ptr, *tok; + char *orig_licenses, *new_licenses = NULL; + int i; + bool put_cnode = false; + + /* Reset job cnode count to a value supported on this hardware + * with this SLURM configuration. The job specification might + * also have a CPU count or geometry that might alter the cnode + * count specified in the job request. */ + for (i = 1; i < (1024 * 1024); i *= 2) { + if (cnode_cnt <= (MIN_CNODES * i)) { + cnode_cnt = (MIN_CNODES * i); + break; + } + } + + if (*license_ptr == NULL) { + xstrfmtcat(*license_ptr, "cnode*%u", cnode_cnt); + return; + } + + orig_licenses = *license_ptr; + tok = strtok_r(orig_licenses, ",", &save_ptr); + while (tok) { + if (!strcmp(tok, "cnode") || !strncmp(tok, "cnode*", 6)) { + xstrfmtcat(new_licenses, "%scnode*%u", sep, cnode_cnt); + put_cnode = true; + } else { + xstrfmtcat(new_licenses, "%s%s", sep, tok); + } + tok = strtok_r(NULL, ",", &save_ptr); + sep = ","; + } + if (!put_cnode) + xstrfmtcat(new_licenses, "%scnode*%u", sep, cnode_cnt); + xfree(orig_licenses); + *license_ptr = new_licenses; +} + +/* Set the job's license specification to include its cnodes requirement */ +extern int job_submit(struct job_descriptor *job_desc, uint32_t submit_uid) +{ + uint32_t cnode_cnt = job_desc->min_nodes; + + xassert(job_desc); + if (cnode_cnt == NO_VAL) + cnode_cnt = MIN_CNODES; + + _rebuild_licenses(&job_desc->licenses, cnode_cnt); + return SLURM_SUCCESS; +} + +extern int job_modify(struct job_descriptor *job_desc, + struct job_record *job_ptr, uint32_t submit_uid) +{ + char **license_ptr; + uint32_t cnode_cnt = job_desc->min_nodes; + + xassert(job_desc); + xassert(job_ptr); + if ((job_desc->licenses == NULL) && job_ptr->licenses) + job_desc->licenses = xstrdup(job_ptr->licenses); + license_ptr = &job_desc->licenses; + + if ((cnode_cnt == NO_VAL) && job_ptr->details) + cnode_cnt = job_ptr->details->min_nodes; + + _rebuild_licenses(license_ptr, cnode_cnt); + + return SLURM_SUCCESS; +} diff --git a/src/plugins/jobcomp/filetxt/jobcomp_filetxt.c b/src/plugins/jobcomp/filetxt/jobcomp_filetxt.c index ee56b37d7..e50dd5d09 100644 --- a/src/plugins/jobcomp/filetxt/jobcomp_filetxt.c +++ b/src/plugins/jobcomp/filetxt/jobcomp_filetxt.c @@ -292,6 +292,10 @@ extern int slurm_jobcomp_log_record ( struct job_record *job_ptr ) if (job_ptr->resize_time) { _make_time_str(&job_ptr->resize_time, start_str, sizeof(start_str)); + } else if (job_ptr->start_time > job_ptr->end_time) { + /* Job cancelled while pending and + * expected start time is in the future. */ + snprintf(start_str, sizeof(start_str), "Unknown"); } else { _make_time_str(&job_ptr->start_time, start_str, sizeof(start_str)); diff --git a/src/plugins/jobcomp/mysql/jobcomp_mysql.c b/src/plugins/jobcomp/mysql/jobcomp_mysql.c index 6fade15e5..9d8755075 100644 --- a/src/plugins/jobcomp/mysql/jobcomp_mysql.c +++ b/src/plugins/jobcomp/mysql/jobcomp_mysql.c @@ -316,7 +316,11 @@ extern int slurm_jobcomp_log_record(struct job_record *job_ptr) job_state = job_ptr->job_state & JOB_STATE_BASE; if (job_ptr->resize_time) start_time = job_ptr->resize_time; - else + else if (job_ptr->start_time > job_ptr->end_time) { + /* Job cancelled while pending and + * expected start time is in the future. */ + start_time = 0; + } else start_time = job_ptr->start_time; end_time = job_ptr->end_time; } diff --git a/src/plugins/jobcomp/pgsql/jobcomp_pgsql.c b/src/plugins/jobcomp/pgsql/jobcomp_pgsql.c index a98f7c40b..ff7d3bb48 100644 --- a/src/plugins/jobcomp/pgsql/jobcomp_pgsql.c +++ b/src/plugins/jobcomp/pgsql/jobcomp_pgsql.c @@ -352,7 +352,11 @@ extern int slurm_jobcomp_log_record(struct job_record *job_ptr) job_state = job_ptr->job_state & JOB_STATE_BASE; if (job_ptr->resize_time) start_time = job_ptr->resize_time; - else + else if (job_ptr->start_time > job_ptr->end_time) { + /* Job cancelled while pending and + * expected start time is in the future. */ + start_time = 0; + } else start_time = job_ptr->start_time; end_time = job_ptr->end_time; } diff --git a/src/plugins/jobcomp/script/jobcomp_script.c b/src/plugins/jobcomp/script/jobcomp_script.c index da7499b03..fe6985ca9 100644 --- a/src/plugins/jobcomp/script/jobcomp_script.c +++ b/src/plugins/jobcomp/script/jobcomp_script.c @@ -1,6 +1,6 @@ /*****************************************************************************\ * jobcomp_script.c - Script running slurm job completion logging plugin. - * $Id: jobcomp_script.c 21212 2010-09-21 22:17:38Z jette $ + * $Id: jobcomp_script.c 22818 2011-03-21 15:20:11Z jette $ ***************************************************************************** * Produced at Center for High Performance Computing, North Dakota State * University @@ -221,7 +221,11 @@ static struct jobcomp_info * _jobcomp_info_create (struct job_record *job) j->jobstate = xstrdup (job_state_string (state)); if (job->resize_time) j->start = job->resize_time; - else + else if (job->start_time > job->end_time) { + /* Job cancelled while pending and + * expected start time is in the future. */ + j->start = 0; + } else j->start = job->start_time; j->end = job->end_time; } diff --git a/src/plugins/sched/backfill/backfill.c b/src/plugins/sched/backfill/backfill.c index 356f14ea4..27532ccea 100644 --- a/src/plugins/sched/backfill/backfill.c +++ b/src/plugins/sched/backfill/backfill.c @@ -228,6 +228,8 @@ static int _num_feature_count(struct job_record *job_ptr) return rc; feat_iter = list_iterator_create(detail_ptr->feature_list); + if (feat_iter == NULL) + fatal("list_iterator_create: malloc failure"); while ((feat_ptr = (struct feature_record *) list_next(feat_iter))) { if (feat_ptr->count) rc++; @@ -269,6 +271,8 @@ static int _try_sched(struct job_record *job_ptr, bitstr_t **avail_bitmap, list_size = list_count(detail_ptr->feature_list); feat_cnt_orig = xmalloc(sizeof(uint16_t) * list_size); feat_iter = list_iterator_create(detail_ptr->feature_list); + if (feat_iter == NULL) + fatal("list_iterator_create: malloc failure"); while ((feat_ptr = (struct feature_record *) list_next(feat_iter))) { high_cnt = MAX(high_cnt, feat_ptr->count); @@ -482,7 +486,7 @@ static int _attempt_backfill(void) if (slurm_get_root_filter()) filter_root = true; - job_queue = build_job_queue(); + job_queue = build_job_queue(true); if (list_count(job_queue) <= 1) { debug("backfill: no jobs to backfill"); list_destroy(job_queue); @@ -511,6 +515,18 @@ static int _attempt_backfill(void) if (debug_flags & DEBUG_FLAG_BACKFILL) info("backfill test for job %u", job_ptr->job_id); + if ((job_ptr->state_reason == WAIT_ASSOC_JOB_LIMIT) || + (job_ptr->state_reason == WAIT_ASSOC_RESOURCE_LIMIT) || + (job_ptr->state_reason == WAIT_ASSOC_TIME_LIMIT)) { + debug2("backfill: job %u is not allowed to run now. " + "Skipping it. State=%s. Reason=%s. Priority=%u", + job_ptr->job_id, + job_state_string(job_ptr->job_state), + job_reason_string(job_ptr->state_reason), + job_ptr->priority); + continue; + } + if (((part_ptr->state_up & PARTITION_SCHED) == 0) || (part_ptr->node_bitmap == NULL)) continue; @@ -554,7 +570,9 @@ static int _attempt_backfill(void) } comp_time_limit = time_limit; orig_time_limit = job_ptr->time_limit; - if (job_ptr->time_min && (job_ptr->time_min < time_limit)) + if (qos_ptr && (qos_ptr->flags & QOS_FLAG_NO_RESERVE)) + time_limit = job_ptr->time_limit = 1; + else if (job_ptr->time_min && (job_ptr->time_min < time_limit)) time_limit = job_ptr->time_limit = job_ptr->time_min; /* Determine impact of any resource reservations */ @@ -605,8 +623,10 @@ static int _attempt_backfill(void) (!bit_super_set(job_ptr->details->req_node_bitmap, avail_bitmap))) || (job_req_node_filter(job_ptr, avail_bitmap))) { - if (later_start) + if (later_start) { + job_ptr->start_time = 0; goto TRY_LATER; + } job_ptr->time_limit = orig_time_limit; continue; } @@ -628,11 +648,16 @@ static int _attempt_backfill(void) } } /* this is the time consuming operation */ + debug2("backfill: entering _try_sched for job %u.", + job_ptr->job_id); j = _try_sched(job_ptr, &avail_bitmap, min_nodes, max_nodes, req_nodes); + debug2("backfill: finished _try_sched for job %u.", + job_ptr->job_id); now = time(NULL); if (j != SLURM_SUCCESS) { job_ptr->time_limit = orig_time_limit; + job_ptr->start_time = 0; continue; /* not runable */ } @@ -642,7 +667,9 @@ static int _attempt_backfill(void) } if (job_ptr->start_time <= now) { int rc = _start_job(job_ptr, resv_bitmap); - if ((rc == SLURM_SUCCESS) && job_ptr->time_min) { + if (qos_ptr && (qos_ptr->flags & QOS_FLAG_NO_RESERVE)) + job_ptr->time_limit = orig_time_limit; + else if ((rc == SLURM_SUCCESS) && job_ptr->time_min) { /* Set time limit as high as possible */ job_ptr->time_limit = comp_time_limit; job_ptr->end_time = job_ptr->start_time + @@ -655,10 +682,12 @@ static int _attempt_backfill(void) } if (rc == ESLURM_ACCOUNTING_POLICY) { /* Unknown future start time, just skip job */ + job_ptr->start_time = 0; continue; } else if (rc != SLURM_SUCCESS) { /* Planned to start job, but something bad * happended. */ + job_ptr->start_time = 0; break; } else { /* Started this job, move to next one */ @@ -670,6 +699,7 @@ static int _attempt_backfill(void) if (later_start && (job_ptr->start_time > later_start)) { /* Try later when some nodes currently reserved for * pending jobs are free */ + job_ptr->start_time = 0; goto TRY_LATER; } @@ -690,6 +720,7 @@ static int _attempt_backfill(void) * job to be backfill scheduled, which the sched * plugin does not know about. Try again later. */ later_start = job_ptr->start_time; + job_ptr->start_time = 0; goto TRY_LATER; } diff --git a/src/plugins/sched/builtin/builtin.c b/src/plugins/sched/builtin/builtin.c index 7e892d32b..b18ed7998 100644 --- a/src/plugins/sched/builtin/builtin.c +++ b/src/plugins/sched/builtin/builtin.c @@ -146,7 +146,7 @@ static void _compute_start_times(void) alloc_bitmap = bit_alloc(node_record_count); if (alloc_bitmap == NULL) fatal("bit_alloc: malloc failure"); - job_queue = build_job_queue(); + job_queue = build_job_queue(true); while ((job_queue_rec = (job_queue_rec_t *) list_pop_bottom(job_queue, sort_job_queue2))) { job_ptr = job_queue_rec->job_ptr; diff --git a/src/plugins/select/bluegene/plugin/bg_job_place.c b/src/plugins/select/bluegene/plugin/bg_job_place.c index f8c5da2b6..88c8031d0 100644 --- a/src/plugins/select/bluegene/plugin/bg_job_place.c +++ b/src/plugins/select/bluegene/plugin/bg_job_place.c @@ -604,8 +604,13 @@ static int _check_for_booted_overlapping_blocks( } } - if ((found_record->job_running != NO_JOB_RUNNING) - || (found_record->state == RM_PARTITION_ERROR)) { + if (((bg_conf->layout_mode == LAYOUT_DYNAMIC) + || ((!SELECT_IS_CHECK_FULL_SET(query_mode) + || SELECT_IS_MODE_RUN_NOW(query_mode)) + && (bg_conf->layout_mode != LAYOUT_DYNAMIC))) + && ((found_record->job_running != NO_JOB_RUNNING) + || (found_record->state + == RM_PARTITION_ERROR))) { if ((found_record->job_running == BLOCK_ERROR_STATE) || (found_record->state @@ -615,16 +620,15 @@ static int _check_for_booted_overlapping_blocks( "is in an error state.", bg_record->bg_block_id, found_record->bg_block_id); - else - if (bg_conf->slurm_debug_flags - & DEBUG_FLAG_BG_PICK) - info("can't use %s, there is " - "a job (%d) running on " - "an overlapping " - "block %s", - bg_record->bg_block_id, - found_record->job_running, - found_record->bg_block_id); + else if (bg_conf->slurm_debug_flags + & DEBUG_FLAG_BG_PICK) + info("can't use %s, there is " + "a job (%d) running on " + "an overlapping " + "block %s", + bg_record->bg_block_id, + found_record->job_running, + found_record->bg_block_id); if (bg_conf->layout_mode == LAYOUT_DYNAMIC) { List tmp_list = list_create(NULL); @@ -1318,8 +1322,17 @@ static int _sync_block_lists(List full_list, List incomp_list) if (bg_record->free_cnt == new_record->free_cnt && bit_equal(bg_record->bitmap, new_record->bitmap) && bit_equal(bg_record->ionode_bitmap, - new_record->ionode_bitmap)) + new_record->ionode_bitmap)) { + /* now make sure the conn_type is the same for + regular sized blocks */ + if ((bg_record->node_cnt + >= bg_conf->bp_node_cnt) + && bg_record->conn_type + != new_record->conn_type) + continue; + break; + } } if (!bg_record) { diff --git a/src/plugins/select/bluegene/plugin/bg_job_run.c b/src/plugins/select/bluegene/plugin/bg_job_run.c index 3a477bd1c..36e5378fb 100644 --- a/src/plugins/select/bluegene/plugin/bg_job_run.c +++ b/src/plugins/select/bluegene/plugin/bg_job_run.c @@ -2,7 +2,7 @@ * bg_job_run.c - blue gene job execution (e.g. initiation and termination) * functions. * - * $Id: bg_job_run.c 22111 2011-01-18 19:04:51Z da $ + * $Id: bg_job_run.c 22476 2011-02-15 00:08:39Z da $ ***************************************************************************** * Copyright (C) 2004-2006 The Regents of the University of California. * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). @@ -602,12 +602,11 @@ static void _start_agent(bg_action_t *bg_action_ptr) bg_action_ptr->reboot = 0; /* Since bg_free_block will unlock block_state_mutex we need to make sure the block we want is still - around. + around. Failure will unlock this so no need to + unlock before return. */ - if (!_make_sure_block_still_exists(bg_action_ptr, bg_record)) { - slurm_mutex_unlock(&block_state_mutex); + if (!_make_sure_block_still_exists(bg_action_ptr, bg_record)) return; - } } delete_list = list_create(NULL); @@ -668,10 +667,10 @@ static void _start_agent(bg_action_t *bg_action_ptr) } slurm_mutex_lock(&block_state_mutex); - if (!_make_sure_block_still_exists(bg_action_ptr, bg_record)) { - slurm_mutex_unlock(&block_state_mutex); + /* Failure will unlock block_state_mutex so no need to unlock before + return. */ + if (!_make_sure_block_still_exists(bg_action_ptr, bg_record)) return; - } if (bg_record->job_running <= NO_JOB_RUNNING) { // _reset_block(bg_record); should already happened @@ -748,10 +747,13 @@ static void _start_agent(bg_action_t *bg_action_ptr) bg_free_block(bg_record, 1, 1); - if (!_make_sure_block_still_exists(bg_action_ptr, bg_record)) { - slurm_mutex_unlock(&block_state_mutex); + /* Since bg_free_block will unlock block_state_mutex + we need to make sure the block we want is still + around. Failure will unlock block_state_mutex so + no need to unlock before return. + */ + if (!_make_sure_block_still_exists(bg_action_ptr, bg_record)) return; - } #ifdef HAVE_BG_FILES #ifdef HAVE_BGL if ((rc = bridge_modify_block(bg_record->bg_block_id, @@ -832,29 +834,33 @@ static void _start_agent(bg_action_t *bg_action_ptr) bg_free_block(bg_record, 1, 1); - if (!_make_sure_block_still_exists(bg_action_ptr, bg_record)) { - slurm_mutex_unlock(&block_state_mutex); + /* Since bg_free_block will unlock block_state_mutex + we need to make sure the block we want is still + around. Failure will unlock block_state_mutex so + no need to unlock before return. + */ + if (!_make_sure_block_still_exists(bg_action_ptr, bg_record)) return; - } + bg_record->modifying = 0; } if (bg_record->state == RM_PARTITION_FREE) { if ((rc = boot_block(bg_record)) != SLURM_SUCCESS) { + /* Since boot_block could unlock block_state_mutex + on error we need to make sure the block we + want is still around. Failure will unlock + block_state_mutex so no need to unlock + before return. + */ if (!_make_sure_block_still_exists(bg_action_ptr, - bg_record)) { - slurm_mutex_unlock(&block_state_mutex); + bg_record)) return; - } _reset_block(bg_record); slurm_mutex_unlock(&block_state_mutex); bg_requeue_job(bg_action_ptr->job_ptr->job_id, 1); return; } - if (!_make_sure_block_still_exists(bg_action_ptr, bg_record)) { - slurm_mutex_unlock(&block_state_mutex); - return; - } } else if (bg_record->state == RM_PARTITION_CONFIGURING) bg_record->boot_state = 1; diff --git a/src/plugins/select/bluegene/plugin/bg_record_functions.c b/src/plugins/select/bluegene/plugin/bg_record_functions.c index bbb6cb9ad..eb8cfc5b7 100644 --- a/src/plugins/select/bluegene/plugin/bg_record_functions.c +++ b/src/plugins/select/bluegene/plugin/bg_record_functions.c @@ -134,6 +134,12 @@ extern int block_exist_in_list(List my_list, bg_record_t *bg_record) if (bit_equal(bg_record->bitmap, found_record->bitmap) && bit_equal(bg_record->ionode_bitmap, found_record->ionode_bitmap)) { + /* now make sure the conn_type is the same for + regular sized blocks */ + if ((bg_record->node_cnt >= bg_conf->bp_node_cnt) + && bg_record->conn_type != found_record->conn_type) + continue; + if (bg_record->ionodes) debug("This block %s[%s] " "is already in the list %s", diff --git a/src/plugins/select/bluegene/plugin/bluegene.c b/src/plugins/select/bluegene/plugin/bluegene.c index 46b9e5927..22555e09e 100644 --- a/src/plugins/select/bluegene/plugin/bluegene.c +++ b/src/plugins/select/bluegene/plugin/bluegene.c @@ -1,7 +1,7 @@ /*****************************************************************************\ * bluegene.c - blue gene node configuration processing module. * - * $Id: bluegene.c 22165 2011-01-21 18:32:00Z da $ + * $Id: bluegene.c 22587 2011-03-01 21:19:25Z da $ ***************************************************************************** * Copyright (C) 2004 The Regents of the University of California. * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). @@ -59,12 +59,10 @@ #define _DEBUG 0 typedef struct { - bg_record_t *bg_record; - pthread_cond_t *free_cond; - int *free_cnt; - pthread_mutex_t *free_mutex; - bool wait; -} bg_free_t; + List track_list; + uint32_t job_id; + bool destroy; +} bg_free_block_list_t; /* Global variables */ @@ -86,7 +84,6 @@ static int _delete_old_blocks(List curr_block_list, List found_block_list); static int _post_block_free(bg_record_t *bg_record, bool restore); static void *_track_freeing_blocks(void *args); -static void *_wait_and_destroy_block(void *args); static char *_get_bg_conf(void); static int _reopen_bridge_log(void); static void _destroy_bitmap(void *object); @@ -499,10 +496,10 @@ extern int bg_free_block(bg_record_t *bg_record, bool wait, bool locked) * the same block twice. It may * had already been removed at this point also. */ +#ifdef HAVE_BG_FILES if (bg_record->state != NO_VAL && bg_record->state != RM_PARTITION_FREE && bg_record->state != RM_PARTITION_DEALLOCATING) { -#ifdef HAVE_BG_FILES if (bg_conf->slurm_debug_flags & DEBUG_FLAG_SELECT_TYPE) info("bridge_destroy %s", bg_record->bg_block_id); @@ -539,12 +536,18 @@ extern int bg_free_block(bg_record_t *bg_record, bool wait, bool locked) bg_record->state); } } + } #else -// bg_record->state = RM_PARTITION_FREE; - if (bg_record->state != RM_PARTITION_FREE) - bg_record->state = RM_PARTITION_DEALLOCATING; + /* Fake a free since we are n deallocating + state before this. + */ + if (bg_record->state == RM_PARTITION_ERROR) + break; + else if (count >= 3) + bg_record->state = RM_PARTITION_FREE; + else if (bg_record->state != RM_PARTITION_FREE) + bg_record->state = RM_PARTITION_DEALLOCATING; #endif - } if (!wait || (bg_record->state == RM_PARTITION_FREE) #ifdef HAVE_BGL @@ -564,7 +567,8 @@ extern int bg_free_block(bg_record_t *bg_record, bool wait, bool locked) } rc = SLURM_SUCCESS; - if (bg_record->state == RM_PARTITION_FREE) + if ((bg_record->state == RM_PARTITION_FREE) + || (bg_record->state == RM_PARTITION_ERROR)) remove_from_bg_list(bg_lists->booted, bg_record); else if (count >= MAX_FREE_RETRIES) { /* Something isn't right, go mark this one in an error @@ -597,19 +601,24 @@ extern int free_block_list(uint32_t job_id, List track_in_list, bg_record_t *bg_record = NULL; int retries; ListIterator itr = NULL; - int track_cnt = 0, free_cnt = 0, retry_cnt = 0, rc = SLURM_SUCCESS; - bool restore = true; - List track_list = list_create(NULL); - if (!track_in_list || !(track_cnt = list_count(track_in_list))) + bg_free_block_list_t *bg_free_list; + pthread_attr_t attr_agent; + pthread_t thread_agent; + + if (!track_in_list || !list_count(track_in_list)) return SLURM_SUCCESS; + bg_free_list = xmalloc(sizeof(bg_free_block_list_t)); + bg_free_list->track_list = list_create(NULL); + bg_free_list->destroy = destroy; + bg_free_list->job_id = job_id; + slurm_mutex_lock(&block_state_mutex); - list_transfer(track_list, track_in_list); - itr = list_iterator_create(track_list); + list_transfer(bg_free_list->track_list, track_in_list); + itr = list_iterator_create(bg_free_list->track_list); while ((bg_record = list_next(itr))) { if (bg_record->magic != BLOCK_MAGIC) { error("block was already destroyed"); - free_cnt++; continue; } @@ -632,118 +641,36 @@ extern int free_block_list(uint32_t job_id, List track_in_list, == SLURM_SUCCESS) num_unused_cpus += bg_record->cpu_cnt; - /* we will wait below */ - if (!wait) { - pthread_attr_t attr_agent; - pthread_t thread_agent; - slurm_attr_init(&attr_agent); - if (pthread_attr_setdetachstate( - &attr_agent, PTHREAD_CREATE_DETACHED)) - error("pthread_attr_setdetachstate error %m"); - retries = 0; - while (pthread_create(&thread_agent, &attr_agent, - _wait_and_destroy_block, - bg_record)) { - error("pthread_create error %m"); - if (++retries > MAX_PTHREAD_RETRIES) - fatal("Can't create " - "pthread"); - /* sleep and retry */ - usleep(1000); - } - - continue; - } bg_free_block(bg_record, 0, 1); } + list_iterator_destroy(itr); slurm_mutex_unlock(&block_state_mutex); - /* _wait_and_destroy_block should handle cleanup, but we - * should start a thread just to make sure we have current - * states, then just return */ - if (!wait) { - pthread_attr_t attr_agent; - pthread_t thread_agent; - slurm_attr_init(&attr_agent); - list_iterator_destroy(itr); - retries = 0; - while (pthread_create(&thread_agent, &attr_agent, - _track_freeing_blocks, - track_list)) { - error("pthread_create error %m"); - if (++retries > MAX_PTHREAD_RETRIES) - fatal("Can't create " - "pthread"); - /* sleep and retry */ - usleep(1000); - } + if (wait) { + /* Track_freeing_blocks waits until the list is done + and frees the memory of bg_free_list. + */ + _track_freeing_blocks(bg_free_list); return SLURM_SUCCESS; } - /* If no block is in error state remove and destroy them. */ - retry_cnt = 0; - debug("Going to free %d for job %u", track_cnt, job_id); - while (retry_cnt < MAX_FREE_RETRIES) { - free_cnt = 0; - slurm_mutex_lock(&block_state_mutex); - /* just to make sure state is updated */ - update_block_list_state(track_list); - list_iterator_reset(itr); - /* just incase things change */ - track_cnt = list_count(track_list); - while ((bg_record = list_next(itr))) { -#ifndef HAVE_BG_FILES - /* Fake a free since we are n deallocating - state before this. - */ - if (retry_cnt >= 3) - bg_record->state = RM_PARTITION_FREE; -#endif - if ((bg_record->state == RM_PARTITION_FREE) - || (bg_record->state == RM_PARTITION_ERROR)) - free_cnt++; - else if (bg_record->state != RM_PARTITION_DEALLOCATING) - bg_free_block(bg_record, 0, 1); - } - slurm_mutex_unlock(&block_state_mutex); - if (free_cnt == track_cnt) - break; - debug("freed %d of %d for job %u", free_cnt, track_cnt, job_id); - sleep(FREE_SLEEP_INTERVAL); - retry_cnt++; + /* _track_freeing_blocks handles cleanup */ + slurm_attr_init(&attr_agent); + if (pthread_attr_setdetachstate(&attr_agent, PTHREAD_CREATE_DETACHED)) + error("pthread_attr_setdetachstate error %m"); + retries = 0; + while (pthread_create(&thread_agent, &attr_agent, + _track_freeing_blocks, + bg_free_list)) { + error("pthread_create error %m"); + if (++retries > MAX_PTHREAD_RETRIES) + fatal("Can't create " + "pthread"); + /* sleep and retry */ + usleep(1000); } - debug("Freed them all for job %u", job_id); - - if ((bg_conf->layout_mode == LAYOUT_DYNAMIC) || destroy) - restore = false; - - /* If there is a block in error state we need to keep all - * these blocks around. */ - slurm_mutex_lock(&block_state_mutex); - list_iterator_reset(itr); - while ((bg_record = list_next(itr))) { - /* block no longer exists */ - if (bg_record->magic != BLOCK_MAGIC) - continue; - if (bg_record->state != RM_PARTITION_FREE) { - restore = true; - rc = SLURM_ERROR; - break; - } - } - slurm_mutex_unlock(&block_state_mutex); - - /* now we need to lock it up. */ - slurm_mutex_lock(&block_state_mutex); - list_iterator_reset(itr); - while ((bg_record = list_next(itr))) - _post_block_free(bg_record, restore); - slurm_mutex_unlock(&block_state_mutex); - last_bg_update = time(NULL); - list_iterator_destroy(itr); - list_destroy(track_list); - - return rc; + slurm_attr_destroy(&attr_agent); + return SLURM_SUCCESS; } /* @@ -1584,7 +1511,8 @@ static int _post_block_free(bg_record_t *bg_record, bool restore) return SLURM_SUCCESS; } - if (bg_record->state != RM_PARTITION_FREE) { + if ((bg_record->state != RM_PARTITION_FREE) + && (bg_record->state != RM_PARTITION_ERROR)){ /* Something isn't right, go mark this one in an error state. */ update_block_msg_t block_msg; @@ -1658,73 +1586,86 @@ static int _post_block_free(bg_record_t *bg_record, bool restore) static void *_track_freeing_blocks(void *args) { - List track_list = (List)args; + bg_free_block_list_t *bg_free_list = (bg_free_block_list_t *)args; + List track_list = bg_free_list->track_list; + bool destroy = bg_free_list->destroy; + uint32_t job_id = bg_free_list->job_id; int retry_cnt = 0; int free_cnt = 0, track_cnt = list_count(track_list); ListIterator itr = list_iterator_create(track_list); bg_record_t *bg_record; + bool restore = true; - debug("_track_freeing_blocks: Going to free %d", track_cnt); + debug("_track_freeing_blocks: Going to free %d for job %u", + track_cnt, job_id); while (retry_cnt < MAX_FREE_RETRIES) { free_cnt = 0; slurm_mutex_lock(&block_state_mutex); + /* just to make sure state is updated */ update_block_list_state(track_list); list_iterator_reset(itr); /* just incase this changes from the update function */ track_cnt = list_count(track_list); while ((bg_record = list_next(itr))) { + if (bg_record->magic != BLOCK_MAGIC) { + /* update_block_list_state should + remove this already from the list + so we shouldn't ever have this. + */ + error("_track_freeing_blocks: block was " + "already destroyed"); + free_cnt++; + continue; + } #ifndef HAVE_BG_FILES /* Fake a free since we are n deallocating state before this. */ - if (retry_cnt >= 3) + if ((bg_record->state != RM_PARTITION_ERROR) + && (retry_cnt >= 3)) bg_record->state = RM_PARTITION_FREE; #endif if ((bg_record->state == RM_PARTITION_FREE) || (bg_record->state == RM_PARTITION_ERROR)) free_cnt++; + else if (bg_record->state != RM_PARTITION_DEALLOCATING) + bg_free_block(bg_record, 0, 1); } slurm_mutex_unlock(&block_state_mutex); if (free_cnt == track_cnt) break; - debug("_track_freeing_blocks: freed %d of %d", - free_cnt, track_cnt); + debug("_track_freeing_blocks: freed %d of %d for job %u", + free_cnt, track_cnt, job_id); sleep(FREE_SLEEP_INTERVAL); retry_cnt++; } - debug("_track_freeing_blocks: Freed them all"); + debug("_track_freeing_blocks: Freed them all for job %u", job_id); - list_iterator_destroy(itr); - list_destroy(track_list); - return NULL; -} + if ((bg_conf->layout_mode == LAYOUT_DYNAMIC) || destroy) + restore = false; -/* This should only be called from a thread */ -static void *_wait_and_destroy_block(void *args) -{ - bg_record_t *bg_record = (bg_record_t *)args; - bool restore = true; + /* If there is a block in error state we need to keep all + * these blocks around. */ slurm_mutex_lock(&block_state_mutex); + list_iterator_reset(itr); + while ((bg_record = list_next(itr))) { + /* block no longer exists */ + if (bg_record->magic != BLOCK_MAGIC) + continue; + if (bg_record->state != RM_PARTITION_FREE) { + restore = true; + break; + } + } - if (!bg_record || (bg_record->magic != BLOCK_MAGIC)) - goto end_it; - - if (bg_conf->slurm_debug_flags & DEBUG_FLAG_SELECT_TYPE) - info("_wait_and_destroy_block: freeing the block %s.", - bg_record->bg_block_id); - bg_free_block(bg_record, 1, 1); - if (bg_conf->slurm_debug_flags & DEBUG_FLAG_SELECT_TYPE) - info("_wait_and_destroy_block: done %s", - bg_record->bg_block_id); - - if ((bg_record->state == RM_PARTITION_FREE) - && (bg_conf->layout_mode == LAYOUT_DYNAMIC)) - restore = false; - - _post_block_free(bg_record, restore); - last_bg_update = time(NULL); -end_it: + list_iterator_reset(itr); + while ((bg_record = list_next(itr))) + _post_block_free(bg_record, restore); slurm_mutex_unlock(&block_state_mutex); + last_bg_update = time(NULL); + list_iterator_destroy(itr); + list_destroy(track_list); + xfree(bg_free_list); return NULL; } diff --git a/src/plugins/select/bluegene/plugin/dynamic_block.c b/src/plugins/select/bluegene/plugin/dynamic_block.c index fdb9ea266..49356700a 100644 --- a/src/plugins/select/bluegene/plugin/dynamic_block.c +++ b/src/plugins/select/bluegene/plugin/dynamic_block.c @@ -75,6 +75,10 @@ extern List create_dynamic_block(List block_list, } memset(&blockreq, 0, sizeof(blockreq_t)); + /* We need to lock this just incase a blocks_overlap is called + which will in turn reset and set the system as it sees fit. + */ + slurm_mutex_lock(&block_state_mutex); if (my_block_list) { reset_ba_system(track_down_nodes); itr = list_iterator_create(my_block_list); @@ -316,8 +320,9 @@ extern List create_dynamic_block(List block_list, itr = list_iterator_create(block_list); itr2 = list_iterator_create(block_list); while ((bg_record = (bg_record_t *) list_next(itr)) != NULL) { - /* never check a block with a job running */ - if (bg_record->job_running != NO_JOB_RUNNING) + /* never check a block being deleted or with a job running */ + if (bg_record->free_cnt + || bg_record->job_running != NO_JOB_RUNNING) continue; /* Here we are only looking for the first @@ -390,6 +395,7 @@ setup_records: finished: reset_all_removed_bps(); + slurm_mutex_unlock(&block_state_mutex); xfree(unusable_nodes); xfree(request->save_name); diff --git a/src/plugins/select/bluegene/plugin/jobinfo.c b/src/plugins/select/bluegene/plugin/jobinfo.c index 4107c8d31..0b621bcf3 100644 --- a/src/plugins/select/bluegene/plugin/jobinfo.c +++ b/src/plugins/select/bluegene/plugin/jobinfo.c @@ -162,9 +162,10 @@ extern int set_select_jobinfo(select_jobinfo_t *jobinfo, #ifdef HAVE_BG_L_P /* Make sure the conn type is correct with the new count */ if ((bg_conf->bp_node_cnt == bg_conf->nodecard_node_cnt) - || (jobinfo->node_cnt < bg_conf->bp_node_cnt)) - jobinfo->conn_type = SELECT_SMALL; - else if (jobinfo->conn_type == SELECT_SMALL) + || (jobinfo->node_cnt < bg_conf->bp_node_cnt)) { + if (jobinfo->conn_type < SELECT_SMALL) + jobinfo->conn_type = SELECT_SMALL; + } else if (jobinfo->conn_type >= SELECT_SMALL) jobinfo->conn_type = SELECT_TORUS; #endif break; diff --git a/src/plugins/select/bluegene/plugin/nodeinfo.c b/src/plugins/select/bluegene/plugin/nodeinfo.c index 5fb55498c..e5c243380 100644 --- a/src/plugins/select/bluegene/plugin/nodeinfo.c +++ b/src/plugins/select/bluegene/plugin/nodeinfo.c @@ -295,8 +295,9 @@ extern int select_nodeinfo_set_all(time_t last_query_time) continue; state = NODE_STATE_ALLOCATED; } else { - error("not sure why we got here with block %s", - bg_record->bg_block_id); + error("not sure why we got here with block %s %s", + bg_record->bg_block_id, + bg_block_state_string(bg_record->state)); continue; } diff --git a/src/plugins/select/cons_res/job_test.c b/src/plugins/select/cons_res/job_test.c index 46df737b2..dbe272bcb 100644 --- a/src/plugins/select/cons_res/job_test.c +++ b/src/plugins/select/cons_res/job_test.c @@ -138,21 +138,16 @@ uint16_t _allocate_sockets(struct job_record *job_ptr, bitstr_t *core_map, uint16_t cores_per_socket = select_node_record[node_i].cores; uint16_t threads_per_core = select_node_record[node_i].vpus; uint16_t min_cores = 1, min_sockets = 1, ntasks_per_socket = 0; - uint16_t max_cores = 0xffff, max_sockets = 0xffff, max_threads = 0xffff; uint16_t ntasks_per_core = 0xffff; if (job_ptr->details && job_ptr->details->mc_ptr) { multi_core_data_t *mc_ptr = job_ptr->details->mc_ptr; if (mc_ptr->cores_per_socket != (uint16_t) NO_VAL) { min_cores = mc_ptr->cores_per_socket; - max_cores = mc_ptr->cores_per_socket; } if (mc_ptr->sockets_per_node != (uint16_t) NO_VAL){ min_sockets = mc_ptr->sockets_per_node; - max_sockets = mc_ptr->sockets_per_node; } - if (mc_ptr->threads_per_core != (uint16_t) NO_VAL) - max_threads = mc_ptr->threads_per_core; if (mc_ptr->ntasks_per_core) { ntasks_per_core = mc_ptr->ntasks_per_core; } @@ -256,23 +251,6 @@ uint16_t _allocate_sockets(struct job_record *job_ptr, bitstr_t *core_map, goto fini; } - /* check max_cores and max_sockets */ - j = 0; - for (i = 0; i < sockets; i++) { - if (free_cores[i] > max_cores) { - /* remove extra cores from this socket */ - uint16_t tmp = free_cores[i] - max_cores; - free_core_count -= tmp; - free_cores[i] -= tmp; - } - if (free_cores[i] > 0) - j++; - if (free_cores[i] && j > max_sockets) { - /* remove extra sockets from use */ - free_core_count -= free_cores[i]; - free_cores[i] = 0; - } - } if (free_core_count < 1) { /* no available resources on this node */ num_tasks = 0; @@ -288,7 +266,6 @@ uint16_t _allocate_sockets(struct job_record *job_ptr, bitstr_t *core_map, */ avail_cpus = 0; num_tasks = 0; - threads_per_core = MIN(threads_per_core, max_threads); threads_per_core = MIN(threads_per_core, ntasks_per_core); for (i = 0; i < sockets; i++) { @@ -410,21 +387,16 @@ uint16_t _allocate_cores(struct job_record *job_ptr, bitstr_t *core_map, uint16_t cores_per_socket = select_node_record[node_i].cores; uint16_t threads_per_core = select_node_record[node_i].vpus; uint16_t min_cores = 1, min_sockets = 1; - uint16_t max_cores = 0xffff, max_sockets = 0xffff, max_threads = 0xffff; uint16_t ntasks_per_core = 0xffff; if (job_ptr->details && job_ptr->details->mc_ptr) { multi_core_data_t *mc_ptr = job_ptr->details->mc_ptr; if (mc_ptr->cores_per_socket != (uint16_t) NO_VAL) { min_cores = mc_ptr->cores_per_socket; - max_cores = mc_ptr->cores_per_socket; } if (mc_ptr->sockets_per_node != (uint16_t) NO_VAL){ min_sockets = mc_ptr->sockets_per_node; - max_sockets = mc_ptr->sockets_per_node; } - if (mc_ptr->threads_per_core != (uint16_t) NO_VAL) - max_threads = mc_ptr->threads_per_core; if (mc_ptr->ntasks_per_core) { ntasks_per_core = mc_ptr->ntasks_per_core; } @@ -492,7 +464,7 @@ uint16_t _allocate_cores(struct job_record *job_ptr, bitstr_t *core_map, } } - /* Step 2a: check min_cores per socket and min_sockets per node */ + /* Step 2: check min_cores per socket and min_sockets per node */ j = 0; for (i = 0; i < sockets; i++) { if (free_cores[i] < min_cores) { @@ -510,23 +482,6 @@ uint16_t _allocate_cores(struct job_record *job_ptr, bitstr_t *core_map, goto fini; } - /* Step 2b: check max_cores per socket and max_sockets per node */ - j = 0; - for (i = 0; i < sockets; i++) { - if (free_cores[i] > max_cores) { - /* remove extra cores from this socket */ - uint16_t tmp = free_cores[i] - max_cores; - free_core_count -= tmp; - free_cores[i] -= tmp; - } - if (free_cores[i] > 0) - j++; - if (free_cores[i] && (j > max_sockets)) { - /* remove extra sockets from use */ - free_core_count -= free_cores[i]; - free_cores[i] = 0; - } - } if (free_core_count < 1) { /* no available resources on this node */ num_tasks = 0; @@ -540,7 +495,6 @@ uint16_t _allocate_cores(struct job_record *job_ptr, bitstr_t *core_map, * Note: cpus_per_task and ntasks_per_core need to play nice * 2 tasks_per_core vs. 2 cpus_per_task */ - threads_per_core = MIN(threads_per_core, max_threads); threads_per_core = MIN(threads_per_core, ntasks_per_core); num_tasks = avail_cpus = threads_per_core; diff --git a/src/plugins/select/cons_res/select_cons_res.c b/src/plugins/select/cons_res/select_cons_res.c index 52f039692..3a937e8a1 100644 --- a/src/plugins/select/cons_res/select_cons_res.c +++ b/src/plugins/select/cons_res/select_cons_res.c @@ -1467,16 +1467,22 @@ static int _will_run_test(struct job_record *job_ptr, bitstr_t *bitmap, } /* Remove the running jobs one at a time from exp_node_cr and try - * scheduling the pending job after each one */ + * scheduling the pending job after each one. */ if (rc != SLURM_SUCCESS) { list_sort(cr_job_list, _cr_job_list_sort); job_iterator = list_iterator_create(cr_job_list); if (job_iterator == NULL) fatal ("memory allocation failure"); while ((tmp_job_ptr = list_next(job_iterator))) { + int ovrlap; + bit_or(bitmap, orig_map); + ovrlap = bit_overlap(bitmap, tmp_job_ptr->node_bitmap); + if (ovrlap == 0) /* job has no usable nodes */ + continue; /* skip it */ + debug2("cons_res: _will_run_test, job %u: overlap=%d", + tmp_job_ptr->job_id, ovrlap); _rm_job_from_res(future_part, future_usage, tmp_job_ptr, 0); - bit_or(bitmap, orig_map); rc = cr_job_test(job_ptr, bitmap, min_nodes, max_nodes, req_nodes, SELECT_MODE_WILL_RUN, cr_type, diff --git a/src/plugins/task/affinity/dist_tasks.c b/src/plugins/task/affinity/dist_tasks.c index 9ad33e3b1..8a4bb9e87 100644 --- a/src/plugins/task/affinity/dist_tasks.c +++ b/src/plugins/task/affinity/dist_tasks.c @@ -637,6 +637,34 @@ static void _blot_mask(bitstr_t *mask, uint16_t blot) } } +/* helper function for _expand_masks() + * foreach task, consider which other tasks have set bits on the same socket */ +static void _blot_mask_sockets(const uint32_t maxtasks, const uint32_t task, + bitstr_t **masks, uint16_t blot) +{ + uint16_t i, j, size = 0; + uint32_t q; + + if (!masks[task]) + return; + + size = bit_size(masks[task]); + for (i = 0; i < size; i++) { + if (bit_test(masks[task], i)) { + /* check if other tasks have set bits on this socket */ + uint16_t start = (i / blot) * blot; + for (j = start; j < start+blot; j++) { + for (q = 0; q < maxtasks; q++) { + if ((q != task) && + bit_test(masks[q], j)) { + bit_set(masks[task], j); + } + } + } + } + } +} + /* foreach mask, expand the mask around the set bits to include the * complete resource to which the set bits are to be bound */ static void _expand_masks(uint16_t cpu_bind_type, const uint32_t maxtasks, @@ -659,7 +687,7 @@ static void _expand_masks(uint16_t cpu_bind_type, const uint32_t maxtasks, if (hw_threads*hw_cores < 2) return; for (i = 0; i < maxtasks; i++) { - _blot_mask(masks[i], hw_threads*hw_cores); + _blot_mask_sockets(maxtasks, i, masks, hw_threads*hw_cores); } return; } @@ -956,7 +984,8 @@ static int _task_layout_lllp_block(launch_tasks_request_msg_t *req, for (t=0; t<max_tasks && req->cpus_per_task>1; t++) { if (!masks[t]) continue; - for (i = 0; i < size; i++) { + c = 0; + for (i = 0; i < size && c<req->cpus_per_task; i++) { if (bit_test(masks[t], i) == 0) continue; for (j=i+1,c=1; j<size && c<req->cpus_per_task;j++) { diff --git a/src/plugins/task/affinity/task_affinity.c b/src/plugins/task/affinity/task_affinity.c index 94d40df30..a7f15d2cc 100644 --- a/src/plugins/task/affinity/task_affinity.c +++ b/src/plugins/task/affinity/task_affinity.c @@ -180,7 +180,8 @@ extern int task_slurmd_launch_request (uint32_t job_id, { char buf_type[100]; - debug("task_slurmd_launch_request: %u %u", job_id, node_id); + debug("task_slurmd_launch_request: %u.%u %u", + job_id, req->job_step_id, node_id); if (((conf->sockets >= 1) && ((conf->cores > 1) || (conf->threads > 1))) diff --git a/src/plugins/task/none/task_none.c b/src/plugins/task/none/task_none.c index f9926274c..e252e37f2 100644 --- a/src/plugins/task/none/task_none.c +++ b/src/plugins/task/none/task_none.c @@ -116,7 +116,8 @@ extern int task_slurmd_launch_request (uint32_t job_id, launch_tasks_request_msg_t *req, uint32_t node_id) { - debug("task_slurmd_launch_request: %u %u", job_id, node_id); + debug("task_slurmd_launch_request: %u.%u %u", + job_id, req->job_step_id, node_id); return SLURM_SUCCESS; } diff --git a/src/sacct/options.c b/src/sacct/options.c index 6d5a92481..5d3edce57 100644 --- a/src/sacct/options.c +++ b/src/sacct/options.c @@ -40,6 +40,7 @@ #include "src/common/proc_args.h" #include "src/common/read_config.h" #include "src/common/parse_time.h" +#include "src/common/uid.h" #include "sacct.h" #include <time.h> @@ -75,22 +76,22 @@ void _help_fields_msg(void) static char *_convert_to_id(char *name, bool gid) { - if(gid) { - struct group *grp; - if (!(grp=getgrnam(name))) { + if (gid) { + gid_t gid; + if ( gid_from_string( name, &gid ) != 0 ) { fprintf(stderr, "Invalid group id: %s\n", name); exit(1); } xfree(name); - name = xstrdup_printf("%d", grp->gr_gid); + name = xstrdup_printf( "%d", (int) gid ); } else { - struct passwd *pwd; - if (!(pwd=getpwnam(name))) { + uid_t uid; + if ( uid_from_string( name, &uid ) != 0 ) { fprintf(stderr, "Invalid user id: %s\n", name); exit(1); } xfree(name); - name = xstrdup_printf("%d", pwd->pw_uid); + name = xstrdup_printf( "%d", (int) uid ); } return name; } @@ -129,10 +130,7 @@ static int _addto_id_char_list(List char_list, char *names, bool gid) name = xmalloc((i-start+1)); memcpy(name, names+start, (i-start)); //info("got %s %d", name, i-start); - if (!isdigit((int) *name)) { - name = _convert_to_id( - name, gid); - } + name = _convert_to_id( name, gid ); while((tmp_char = list_next(itr))) { if(!strcasecmp(tmp_char, name)) @@ -160,10 +158,7 @@ static int _addto_id_char_list(List char_list, char *names, bool gid) if((i-start) > 0) { name = xmalloc((i-start)+1); memcpy(name, names+start, (i-start)); - - if (!isdigit((int) *name)) { - name = _convert_to_id(name, gid); - } + name = _convert_to_id(name, gid); while((tmp_char = list_next(itr))) { if(!strcasecmp(tmp_char, name)) diff --git a/src/sacctmgr/archive_functions.c b/src/sacctmgr/archive_functions.c index a2e336466..ec0cb8b85 100644 --- a/src/sacctmgr/archive_functions.c +++ b/src/sacctmgr/archive_functions.c @@ -41,6 +41,18 @@ #include "src/sacctmgr/sacctmgr.h" #include <sys/param.h> /* MAXPATHLEN */ #include "src/common/proc_args.h" +#include "src/common/uid.h" + +static char *_string_to_uid( char *name ) +{ + uid_t uid; + if ( uid_from_string( name, &uid ) != 0 ) { + fprintf(stderr, "Invalid user id: %s\n", name); + exit(1); + } + xfree(name); + return xstrdup_printf( "%d", (int) uid ); +} /* returns number of objects added to list */ extern int _addto_uid_char_list(List char_list, char *names) @@ -76,19 +88,7 @@ extern int _addto_uid_char_list(List char_list, char *names) name = xmalloc((i-start+1)); memcpy(name, names+start, (i-start)); //info("got %s %d", name, i-start); - if (!isdigit((int) *name)) { - struct passwd *pwd; - if (!(pwd=getpwnam(name))) { - fprintf(stderr, - "Invalid user " - "id: %s\n", - name); - exit(1); - } - xfree(name); - name = xstrdup_printf( - "%d", pwd->pw_uid); - } + name = _string_to_uid( name ); while((tmp_char = list_next(itr))) { if(!strcasecmp(tmp_char, name)) @@ -116,18 +116,7 @@ extern int _addto_uid_char_list(List char_list, char *names) if((i-start) > 0) { name = xmalloc((i-start)+1); memcpy(name, names+start, (i-start)); - - if (!isdigit((int) *name)) { - struct passwd *pwd; - if (!(pwd=getpwnam(name))) { - fprintf(stderr, - "Invalid user id: %s\n", - name); - exit(1); - } - xfree(name); - name = xstrdup_printf("%d", pwd->pw_uid); - } + name = _string_to_uid( name ); while((tmp_char = list_next(itr))) { if(!strcasecmp(tmp_char, name)) diff --git a/src/sacctmgr/cluster_functions.c b/src/sacctmgr/cluster_functions.c index e56ac8e3a..3f7d0b6b4 100644 --- a/src/sacctmgr/cluster_functions.c +++ b/src/sacctmgr/cluster_functions.c @@ -1083,7 +1083,13 @@ extern int sacctmgr_dump_cluster (int argc, char *argv[]) acct_list = acct_storage_g_get_accounts(db_conn, my_uid, NULL); - fd = fopen(file_name, "w"); + if ((fd = fopen(file_name,"w")) == NULL) { + fprintf(stderr, "Can't open file %s, %m\n", file_name); + list_destroy(assoc_list); + xfree(cluster_name); + return SLURM_ERROR; + } + /* Add header */ if(fprintf(fd, "# To edit this file start with a cluster line " diff --git a/src/sacctmgr/event_functions.c b/src/sacctmgr/event_functions.c index 3520bf34b..f5cbf720e 100644 --- a/src/sacctmgr/event_functions.c +++ b/src/sacctmgr/event_functions.c @@ -169,22 +169,22 @@ static int _addto_state_char_list(List char_list, char *names) static char *_convert_to_id(char *name, bool gid) { - if(gid) { - struct group *grp; - if (!(grp=getgrnam(name))) { + if (gid) { + gid_t gid; + if ( gid_from_string( name, &gid ) != 0 ) { fprintf(stderr, "Invalid group id: %s\n", name); exit(1); } xfree(name); - name = xstrdup_printf("%d", grp->gr_gid); + name = xstrdup_printf( "%d", (int) gid ); } else { - struct passwd *pwd; - if (!(pwd=getpwnam(name))) { + uid_t uid; + if ( uid_from_string( name, &uid ) != 0 ) { fprintf(stderr, "Invalid user id: %s\n", name); exit(1); } xfree(name); - name = xstrdup_printf("%d", pwd->pw_uid); + name = xstrdup_printf( "%d", (int) uid ); } return name; } @@ -223,10 +223,7 @@ static int _addto_id_char_list(List char_list, char *names, bool gid) name = xmalloc((i-start+1)); memcpy(name, names+start, (i-start)); //info("got %s %d", name, i-start); - if (!isdigit((int) *name)) { - name = _convert_to_id( - name, gid); - } + name = _convert_to_id( name, gid ); while((tmp_char = list_next(itr))) { if(!strcasecmp(tmp_char, name)) @@ -254,10 +251,7 @@ static int _addto_id_char_list(List char_list, char *names, bool gid) if((i-start) > 0) { name = xmalloc((i-start)+1); memcpy(name, names+start, (i-start)); - - if (!isdigit((int) *name)) { - name = _convert_to_id(name, gid); - } + name = _convert_to_id(name, gid); while((tmp_char = list_next(itr))) { if(!strcasecmp(tmp_char, name)) diff --git a/src/sacctmgr/file_functions.c b/src/sacctmgr/file_functions.c index 40de864ad..13ccade8f 100644 --- a/src/sacctmgr/file_functions.c +++ b/src/sacctmgr/file_functions.c @@ -217,10 +217,14 @@ static void _destroy_sacctmgr_file_opts(void *object) xfree(file_opts->name); xfree(file_opts->org); xfree(file_opts->part); - if (file_opts->qos_list) + if (file_opts->qos_list) { list_destroy(file_opts->qos_list); - if (file_opts->wckey_list) + file_opts->qos_list = NULL; + } + if (file_opts->wckey_list) { list_destroy(file_opts->wckey_list); + file_opts->wckey_list = NULL; + } xfree(file_opts); } } diff --git a/src/sacctmgr/qos_functions.c b/src/sacctmgr/qos_functions.c index ecd4c8b59..a2a7c71a9 100644 --- a/src/sacctmgr/qos_functions.c +++ b/src/sacctmgr/qos_functions.c @@ -574,6 +574,7 @@ extern int sacctmgr_add_qos(int argc, char *argv[]) qos = NULL; if(!sacctmgr_find_qos_from_list(g_qos_list, name)) { qos = xmalloc(sizeof(slurmdb_qos_rec_t)); + slurmdb_init_qos_rec(qos, 0); qos->name = xstrdup(name); if(start_qos->description) qos->description = @@ -601,6 +602,7 @@ extern int sacctmgr_add_qos(int argc, char *argv[]) qos->priority = start_qos->priority; qos->usage_factor = start_qos->usage_factor; + qos->usage_thres = start_qos->usage_thres; xstrfmtcat(qos_str, " %s\n", name); list_append(qos_list, qos); diff --git a/src/sacctmgr/user_functions.c b/src/sacctmgr/user_functions.c index eeb8c08ec..e59aa2d26 100644 --- a/src/sacctmgr/user_functions.c +++ b/src/sacctmgr/user_functions.c @@ -940,7 +940,7 @@ extern int sacctmgr_add_user(int argc, char *argv[]) "doesn't exist.\n" " Contact your admin " "to add this account.\n", - default_acct); + local_def_acct); xfree(local_def_acct); xfree(local_def_wckey); continue; @@ -1512,7 +1512,9 @@ extern int sacctmgr_list_user(int argc, char *argv[]) if (!curr_cluster || strcmp(curr_cluster, assoc->cluster)) { slurmdb_association_rec_t *assoc2; - /* we shouldn't have to reset this */ + /* We shouldn't have to reset this + * unless no default is on the + * cluster. */ while ((assoc2 = list_next(itr4))) { if (!assoc2->is_def || strcmp(assoc->cluster, @@ -1525,10 +1527,17 @@ extern int sacctmgr_list_user(int argc, char *argv[]) break; } + /* This means there wasn't a + default on the current cluster. + */ + if (!assoc2) + list_iterator_reset(itr4); if (curr_cluster && wckey_itr) { slurmdb_wckey_rec_t *wckey; - /* we shouldn't have - * to reset this */ + /* We shouldn't have + * to reset this + * unless no default + * is on the cluster. */ while ((wckey = list_next(wckey_itr))) { if (!wckey->is_def || @@ -1544,6 +1553,14 @@ extern int sacctmgr_list_user(int argc, char *argv[]) name); break; } + + /* This means there wasn't a + default on the + current cluster. + */ + if (!wckey) + list_iterator_reset( + wckey_itr); } } diff --git a/src/salloc/salloc.c b/src/salloc/salloc.c index 19224b497..a36ef2fc9 100644 --- a/src/salloc/salloc.c +++ b/src/salloc/salloc.c @@ -156,33 +156,13 @@ int main(int argc, char *argv[]) char **env = NULL; int status = 0; int retries = 0; - pid_t pid = 0; + pid_t pid = getpid(); + pid_t tpgid = 0; pid_t rc_pid = 0; int i, rc = 0; static char *msg = "Slurm job queue full, sleeping and retrying."; slurm_allocation_callbacks_t callbacks; - is_interactive = isatty(STDIN_FILENO); - if (is_interactive) { - bool sent_msg = false; - /* Wait as long as we are running in the background */ - while (tcgetpgrp(STDIN_FILENO) != (pid = getpgrp())) { - if (!sent_msg) { - error("Waiting for program to be placed in " - "the foreground"); - sent_msg = true; - } - killpg(pid, SIGTTIN); - } - - /* - * Save tty attributes and reset at exit, in case a child - * process died before properly resetting terminal. - */ - tcgetattr (STDIN_FILENO, &saved_tty_attributes); - atexit (_reset_input_mode); - } - log_init(xbasename(argv[0]), logopt, 0, NULL); _set_exit_code(); @@ -236,6 +216,48 @@ int main(int argc, char *argv[]) _set_rlimits(env); } + /* + * Job control for interactive salloc sessions: only if ... + * + * a) input is from a terminal (stdin has valid termios attributes), + * b) controlling terminal exists (non-negative tpgid), + * c) salloc is not run in allocation-only (--no-shell) mode, + * d) salloc runs in its own process group (true in interactive + * shells that support job control), + * e) salloc has been configured at compile-time to support background + * execution and is not currently in the background process group. + */ + if (tcgetattr(STDIN_FILENO, &saved_tty_attributes) < 0) { + /* + * Test existence of controlling terminal (tpgid > 0) + * after first making sure stdin is not redirected. + */ + } else if ((tpgid = tcgetpgrp(STDIN_FILENO)) < 0) { + if (!opt.no_shell) { + error("no controlling terminal: please set --no-shell"); + exit(error_exit); + } + } else if ((!opt.no_shell) && (pid == getpgrp())) { + if (tpgid == pid) + is_interactive = true; +#ifdef SALLOC_RUN_FOREGROUND + while (tcgetpgrp(STDIN_FILENO) != pid) { + if (!is_interactive) { + error("Waiting for program to be placed in " + "the foreground"); + is_interactive = true; + } + killpg(pid, SIGTTIN); + } +#endif + } + /* + * Reset saved tty attributes at exit, in case a child + * process died before properly resetting terminal. + */ + if (is_interactive) + atexit (_reset_input_mode); + /* * Request a job allocation */ @@ -287,6 +309,7 @@ int main(int argc, char *argv[]) if (alloc == NULL) { if (allocation_interrupted) { /* cancelled by signal */ + info("Job aborted due to signal"); } else if (errno == EINTR) { error("Interrupted by signal." " Allocation request rescinded."); diff --git a/src/sbatch/mult_cluster.c b/src/sbatch/mult_cluster.c index 7e52f3663..cd0dd3f7f 100644 --- a/src/sbatch/mult_cluster.c +++ b/src/sbatch/mult_cluster.c @@ -178,12 +178,9 @@ extern int sbatch_set_first_avail_cluster(job_desc_msg_t *req) fatal("list_create malloc failure"); itr = list_iterator_create(opt.clusters); while ((working_cluster_rec = list_next(itr))) { - if ((local_cluster = _job_will_run(req))) { - if (!ret_list) - ret_list = list_create( - _destroy_local_cluster_rec); + if ((local_cluster = _job_will_run(req))) list_append(ret_list, local_cluster); - } else + else error("Problem with submit to cluster %s: %m", working_cluster_rec->name); } @@ -192,9 +189,10 @@ extern int sbatch_set_first_avail_cluster(job_desc_msg_t *req) if (host_set) req->alloc_node = NULL; - if (!ret_list) { + if (!list_count(ret_list)) { error("Can't run on any of the clusters given"); - return SLURM_ERROR; + rc = SLURM_ERROR; + goto end_it; } /* sort the list so the first spot is on top */ @@ -205,6 +203,7 @@ extern int sbatch_set_first_avail_cluster(job_desc_msg_t *req) /* set up the working cluster and be done */ working_cluster_rec = local_cluster->cluster_rec; +end_it: list_destroy(ret_list); return rc; diff --git a/src/scancel/opt.c b/src/scancel/opt.c index d1048fe07..b5177c79c 100644 --- a/src/scancel/opt.c +++ b/src/scancel/opt.c @@ -68,6 +68,7 @@ #include "src/common/xmalloc.h" #include "src/common/xstring.h" #include "src/common/proc_args.h" +#include "src/common/uid.h" #include "src/scancel/scancel.h" @@ -233,7 +234,7 @@ static void _opt_env() char *val; if ( (val=getenv("SCANCEL_ACCOUNT")) ) { - opt.account = xstrdup(val); + opt.account = xstrtolower(xstrdup(val)); } if ( (val=getenv("SCANCEL_BATCH")) ) { @@ -276,7 +277,7 @@ static void _opt_env() } if ( (val=getenv("SCANCEL_QOS")) ) { - opt.qos = xstrdup(val); + opt.qos = xstrtolower(xstrdup(val)); } if ( (val=getenv("SCANCEL_STATE")) ) { @@ -347,7 +348,7 @@ static void _opt_args(int argc, char **argv) exit(1); break; case (int)'A': - opt.account = xstrdup(optarg); + opt.account = xstrtolower(xstrdup(optarg)); break; case (int)'b': opt.batch = true; @@ -380,7 +381,7 @@ static void _opt_args(int argc, char **argv) opt.verbose = -1; break; case (int)'q': - opt.qos = xstrdup(optarg); + opt.qos = xstrtolower(xstrdup(optarg)); break; case (int)'R': opt.reservation = xstrdup(optarg); @@ -475,15 +476,11 @@ static bool _opt_verify(void) { bool verified = true; - struct passwd *passwd_ptr; if (opt.user_name) { /* translate to user_id */ - passwd_ptr = getpwnam (opt.user_name); - if (passwd_ptr == NULL) { + if ( uid_from_string( opt.user_name, &opt.user_id ) != 0 ) { error("Invalid user name: %s", opt.user_name); return false; - } else { - opt.user_id = passwd_ptr->pw_uid; } } diff --git a/src/scancel/scancel.c b/src/scancel/scancel.c index 8ca26a06e..099e445a3 100644 --- a/src/scancel/scancel.c +++ b/src/scancel/scancel.c @@ -439,7 +439,7 @@ _cancel_job_id (void *ci) { int error_code = SLURM_SUCCESS, i; bool sig_set = true; - + bool msg_to_ctld = opt.ctld; job_cancel_info_t *cancel_info = (job_cancel_info_t *)ci; uint32_t job_id = cancel_info->job_id; uint16_t sig = cancel_info->sig; @@ -455,21 +455,26 @@ _cancel_job_id (void *ci) else verbose("Signal %u to job %u", sig, job_id); - if ((!sig_set) || opt.ctld) { + if ((sig == SIGKILL) || (!sig_set) || msg_to_ctld) { error_code = slurm_kill_job (job_id, sig, (uint16_t)opt.batch); } else { - if (opt.batch) + if (opt.batch) { error_code = slurm_signal_job_step( job_id, SLURM_BATCH_SCRIPT, sig); - else + } else { error_code = slurm_signal_job (job_id, sig); + } + if (error_code && (errno == ESLURM_JOB_PENDING)) { + /* Send request to directly to slurmctld */ + msg_to_ctld = true; + continue; + } } - if (error_code == 0 - || (errno != ESLURM_TRANSITION_STATE_NO_UPDATE - && errno != ESLURM_JOB_PENDING)) + if ((error_code == 0) || + (errno != ESLURM_TRANSITION_STATE_NO_UPDATE)) break; verbose("Job is in transistional state, retrying"); sleep ( 5 + i ); diff --git a/src/scontrol/scontrol.c b/src/scontrol/scontrol.c index a4ec5dc9b..6c79e6f70 100644 --- a/src/scontrol/scontrol.c +++ b/src/scontrol/scontrol.c @@ -71,6 +71,7 @@ static void _ping_slurmctld(char *control_machine, char *backup_controller); static void _print_config (char *config_param); static void _print_daemons (void); +static void _print_aliases (char* node_hostname); static void _print_ping (void); static void _print_slurmd(char *hostlist); static void _print_version( void ); @@ -490,6 +491,40 @@ _print_daemons (void) fprintf (stdout, "%s\n", daemon_list) ; } +/* + * _print_aliases - report which aliases should be running on this node + */ +static void +_print_aliases (char* node_hostname) +{ + char me[MAX_SLURM_NAME], *n = NULL, *a = NULL; + char *s; + + slurm_conf_init(NULL); + if (!node_hostname) { + gethostname_short(me, MAX_SLURM_NAME); + s = me; + } else + s = node_hostname; + + if (!(n = slurm_conf_get_aliases(s)) && (s == me)) { + + if (!(a = slurm_conf_get_aliased_nodename())) + a = slurm_conf_get_nodename("localhost"); + + if (a) { + n = slurm_conf_get_aliases(a); + xfree(a); + } + } + + if (n) { + fprintf(stdout, "%s\n", n); + xfree(n); + } + +} + /* * _process_command - process the user's command * IN argc - count of arguments @@ -677,7 +712,7 @@ _process_command (int argc, char *argv[]) if (argc > 2) { exit_code = 1; fprintf (stderr, "too many arguments for keyword:%s\n", - tag); + tag); } error_code = slurm_reconfigure(); if (error_code) { @@ -691,15 +726,15 @@ _process_command (int argc, char *argv[]) exit_code = 1; if (quiet_flag != 1) fprintf(stderr, - "too many arguments for keyword:%s\n", - tag); + "too many arguments for keyword:%s\n", + tag); } else if (argc < 3) { exit_code = 1; if (quiet_flag != 1) fprintf(stderr, - "too few arguments for keyword:%s\n", - tag); + "too few arguments for keyword:%s\n", + tag); } else { error_code = scontrol_checkpoint(argv[1], argv[2], @@ -738,7 +773,7 @@ _process_command (int argc, char *argv[]) else if ((strncasecmp (tag, "hold", 4) == 0) || (strncasecmp (tag, "holdu", 5) == 0) || (strncasecmp (tag, "uhold", 5) == 0) || - (strncasecmp (tag, "release", MAX(taglen, 3)) == 0)) { + (strncasecmp (tag, "release", MAX(taglen, 3)) == 0)) { if (argc > 2) { exit_code = 1; if (quiet_flag != 1) @@ -762,7 +797,7 @@ _process_command (int argc, char *argv[]) } } else if ((strncasecmp (tag, "suspend", MAX(taglen, 2)) == 0) || - (strncasecmp (tag, "resume", MAX(taglen, 3)) == 0)) { + (strncasecmp (tag, "resume", MAX(taglen, 3)) == 0)) { if (argc > 2) { exit_code = 1; if (quiet_flag != 1) @@ -1155,15 +1190,15 @@ _show_it (int argc, char *argv[]) exit_code = 1; if (quiet_flag != 1) fprintf(stderr, - "too many arguments for keyword:%s\n", - argv[0]); + "too many arguments for keyword:%s\n", + argv[0]); return; } else if (argc < 2) { exit_code = 1; if (quiet_flag != 1) fprintf(stderr, - "too few arguments for keyword:%s\n", argv[0]); + "too few arguments for keyword:%s\n", argv[0]); return; } @@ -1188,10 +1223,15 @@ _show_it (int argc, char *argv[]) exit_code = 1; if (quiet_flag != 1) fprintf(stderr, - "too many arguments for keyword:%s\n", - argv[0]); + "too many arguments for keyword:%s\n", + argv[0]); } _print_daemons (); + } else if (strncasecmp (tag, "aliases", MAX(taglen, 1)) == 0) { + if (val) + _print_aliases (val); + else + _print_aliases (NULL); } else if (strncasecmp (tag, "jobs", MAX(taglen, 1)) == 0 || strncasecmp (tag, "jobid", MAX(taglen, 1)) == 0 ) { scontrol_print_job (val); @@ -1377,7 +1417,8 @@ _update_bluegene_block (int argc, char *argv[]) argv[i]); fprintf (stderr, "Acceptable State values " - "are FREE, ERROR, RECREATE, REMOVE\n"); + "are ERROR, FREE, RECREATE, " + "REMOVE, RESUME\n"); return 0; } update_cnt++; @@ -1522,41 +1563,41 @@ scontrol [<OPTION>] [<COMMAND>] \n\ -Q or --quiet: equivalent to \"quiet\" command \n\ -v or --verbose: equivalent to \"verbose\" command \n\ -V or --version: equivalent to \"version\" command \n\ - \n\ + \n\ <keyword> may be omitted from the execute line and scontrol will execute \n\ in interactive mode. It will process commands as entered until explicitly\n\ terminated. \n\ - \n\ + \n\ Valid <COMMAND> values are: \n\ abort shutdown slurm controller immediately \n\ - generating a core file. \n\ + generating a core file. \n\ all display information about all partitions, \n\ - including hidden partitions. \n\ + including hidden partitions. \n\ cluster cluster to issue commands to. Default is \n\ - current cluster. cluster with no name will \n\ - reset to default. \n\ + current cluster. cluster with no name will \n\ + reset to default. \n\ checkpoint <CH_OP><ID> perform a checkpoint operation on identified \n\ - job or job step \n\ + job or job step \n\ completing display jobs in completing state along with \n\ - their completing or down nodes \n\ + their completing or down nodes \n\ create <SPECIFICATIONS> create a new partition or reservation \n\ details evokes additional details from the \"show\" \n\ - command \n\ + command \n\ delete <SPECIFICATIONS> delete the specified partition or reservation\n\ - On Dynamic layout Bluegene systems you can also\n\ - delete blocks. \n\ + On Dynamic layout Bluegene systems you can also\n\ + delete blocks. \n\ exit terminate scontrol \n\ help print this description of use. \n\ hold <job_id> prevent specified job from starting (see release)\n\ holdu <job_id> place user hold on specified job (see release)\n\ hide do not display information about hidden \n\ - partitions \n\ + partitions \n\ listpids <job_id<.step>> List pids associated with the given jobid, or\n\ - all jobs if no id is given (This will only \n\ - display the processes on the node which the \n\ - scontrol is ran on, and only for those \n\ - processes spawned by SLURM and their \n\ - descendants) \n\ + all jobs if no id is given (This will only \n\ + display the processes on the node which the \n\ + scontrol is ran on, and only for those \n\ + processes spawned by SLURM and their \n\ + descendants) \n\ notify <job_id> msg send message to specified job \n\ oneliner report output one record per line. \n\ pidinfo <pid> return slurm job information for given pid. \n\ @@ -1570,47 +1611,47 @@ scontrol [<OPTION>] [<COMMAND>] \n\ setdebug <level> set slurmctld debug level \n\ schedloglevel <slevel> set scheduler log level \n\ show <ENTITY> [<ID>] display state of identified entity, default \n\ - is all records. \n\ + is all records. \n\ shutdown <OPTS> shutdown slurm daemons \n\ - (the primary controller will be stopped) \n\ + (the primary controller will be stopped) \n\ suspend <job_id> susend specified job (see resume) \n\ takeover ask slurm backup controller to take over \n\ uhold <job_id> place user hold on specified job (see release)\n\ update <SPECIFICATIONS> update job, node, partition, reservation, \n\ - step or bluegene block/subbp configuration \n\ + step or bluegene block/subbp configuration \n\ verbose enable detailed logging. \n\ version display tool version number. \n\ wait_job <job_id> wait until the nodes allocated to the job \n\ - are booted and usable \n\ + are booted and usable \n\ !! Repeat the last command entered. \n\ - \n\ - <ENTITY> may be \"config\", \"daemons\", \"job\", \"node\", \"partition\"\n\ - \"reservation\", \"hostlist\", \"hostnames\", \"slurmd\", \n\ - \"topology\", or \"step\" \n\ + \n\ + <ENTITY> may be \"aliases\", \"config\", \"daemons\", \"job\", \n\ + \"node\", \"partition\", \"reservation\", \"hostlist\", \n\ + \"hostnames\", \"slurmd\", \"topology\", or \"step\" \n\ (also for BlueGene only: \"block\" or \"subbp\"). \n\ - \n\ + \n\ <ID> may be a configuration parameter name, job id, node name, partition \n\ name, reservation name, job step id, or hostlist or pathname to a \n\ list of host names. \n\ - \n\ + \n\ <HOSTLIST> may either be a comma separated list of host names or the \n\ absolute pathname of a file (with leading '/' containing host names \n\ either separated by commas or new-lines \n\ - \n\ + \n\ <LEVEL> may be an integer value like SlurmctldDebug in the slurm.conf \n\ file or the name of the most detailed errors to report (e.g. \"info\",\n\ \"verbose\", \"debug\", \"debug2\", etc.). \n\ - \n\ + \n\ <SLEVEL> may be an integer value like SlurmSchedLogLevel in the \n\ slurm.conf file or \"enable\" or \"disable\". \n\ - \n\ + \n\ <OPTS> may be \"slurmctld\" to shutdown just the slurmctld daemon, \n\ otherwise all slurm daemons are shutdown \n\ - \n\ + \n\ Node names may be specified using simple range expressions, \n\ (e.g. \"lx[10-20]\" corresponds to lx10, lx11, lx12, ...) \n\ The job step id is the job id followed by a period and the step id. \n\ - \n\ + \n\ <SPECIFICATIONS> are specified in the same format as the configuration \n\ file. You may wish to use the \"show\" keyword then use its output as \n\ input for the update keyword, editing as needed. Bluegene blocks/subbps \n\ @@ -1618,12 +1659,12 @@ scontrol [<OPTION>] [<COMMAND>] \n\ blocks by specifying 'remove' as the state. The remove option is only \n\ valid on Dynamic layout systems. \n\ (Bluegene systems only) \n\ - \n\ + \n\ <CH_OP> identify checkpoint operations and may be \"able\", \"disable\", \n\ \"enable\", \"create\", \"vacate\", \"requeue\", \"restart\", or \"error\"\n\ Additional options include \"ImageDir=<dir>\", \"MaxWait=<seconds>\" and \n\ \"StickToNodes\" \n\ - \n\ + \n\ All commands and options are case-insensitive, although node names and \n\ partition names tests are case-sensitive (node names \"LX\" and \"lx\" \n\ are distinct). \n\n"); diff --git a/src/scontrol/update_job.c b/src/scontrol/update_job.c index 4de0ef80e..b4c1094c3 100644 --- a/src/scontrol/update_job.c +++ b/src/scontrol/update_job.c @@ -246,7 +246,7 @@ scontrol_hold(char *op, char *job_id_str) job_msg.priority = 0; job_msg.alloc_sid = 0; } else - job_msg.priority = 1; + job_msg.priority = INFINITE; if (slurm_update_job(&job_msg)) return slurm_get_errno(); diff --git a/src/slurmctld/acct_policy.c b/src/slurmctld/acct_policy.c index 36b1c6ac9..60beb3353 100644 --- a/src/slurmctld/acct_policy.c +++ b/src/slurmctld/acct_policy.c @@ -292,7 +292,7 @@ extern bool acct_policy_validate(job_desc_msg_t *job_desc, slurmdb_qos_rec_t *qos_ptr, uint16_t *limit_set_max_cpus, uint16_t *limit_set_max_nodes, - uint16_t *limit_set_time) + uint16_t *limit_set_time, bool update_call) { uint32_t time_limit; slurmdb_association_rec_t *assoc_ptr = assoc_in; @@ -314,80 +314,80 @@ extern bool acct_policy_validate(job_desc_msg_t *job_desc, user_name = assoc_ptr->user; assoc_mgr_lock(&locks); - if(qos_ptr) { + if (qos_ptr) { /* for validation we don't need to look at * qos_ptr->grp_cpu_mins. */ - if (((*limit_set_max_cpus) != ADMIN_SET_LIMIT) - && (qos_ptr->grp_cpus != INFINITE)) { - if (job_desc->min_cpus > qos_ptr->grp_cpus) { - info("job submit for user %s(%u): " - "min cpu request %u exceeds " - "group max cpu limit %u for qos '%s'", - user_name, - job_desc->user_id, - job_desc->min_cpus, - qos_ptr->grp_cpus, - qos_ptr->name); - rc = false; - goto end_it; - } else if ((job_desc->max_cpus == NO_VAL) - || ((*limit_set_max_cpus) - && (job_desc->max_cpus - > qos_ptr->grp_cpus))) { - job_desc->max_cpus = qos_ptr->grp_cpus; + if (((*limit_set_max_cpus) == ADMIN_SET_LIMIT) + || (qos_ptr->grp_cpus == INFINITE) + || (update_call && (job_desc->max_cpus == NO_VAL))) { + /* no need to check/set */ + } else if ((job_desc->min_cpus != NO_VAL) + && (job_desc->min_cpus > qos_ptr->grp_cpus)) { + info("job submit for user %s(%u): " + "min cpu request %u exceeds " + "group max cpu limit %u for qos '%s'", + user_name, + job_desc->user_id, + job_desc->min_cpus, + qos_ptr->grp_cpus, + qos_ptr->name); + rc = false; + goto end_it; + } else if ((job_desc->max_cpus == NO_VAL) + || ((*limit_set_max_cpus) + && (job_desc->max_cpus > qos_ptr->grp_cpus))) { + job_desc->max_cpus = qos_ptr->grp_cpus; + (*limit_set_max_cpus) = 1; + } else if (job_desc->max_cpus > qos_ptr->grp_cpus) { + info("job submit for user %s(%u): " + "max cpu changed %u -> %u because " + "of qos limit", + user_name, + job_desc->user_id, + job_desc->max_cpus, + qos_ptr->grp_cpus); + if (job_desc->max_cpus == NO_VAL) (*limit_set_max_cpus) = 1; - } else if (job_desc->max_cpus > - qos_ptr->grp_cpus) { - info("job submit for user %s(%u): " - "max cpu changed %u -> %u because " - "of qos limit", - user_name, - job_desc->user_id, - job_desc->max_cpus, - qos_ptr->grp_cpus); - if(job_desc->max_cpus == NO_VAL) - (*limit_set_max_cpus) = 1; - job_desc->max_cpus = qos_ptr->grp_cpus; - } + job_desc->max_cpus = qos_ptr->grp_cpus; } /* for validation we don't need to look at * qos_ptr->grp_jobs. */ - if (((*limit_set_max_nodes) != ADMIN_SET_LIMIT) - && (qos_ptr->grp_nodes != INFINITE)) { - if (job_desc->min_nodes > qos_ptr->grp_nodes) { - info("job submit for user %s(%u): " - "min node request %u exceeds " - "group max node limit %u for qos '%s'", - user_name, - job_desc->user_id, - job_desc->min_nodes, - qos_ptr->grp_nodes, - qos_ptr->name); - rc = false; - goto end_it; - } else if (job_desc->max_nodes == 0 - || ((*limit_set_max_nodes) - && (job_desc->max_nodes - > qos_ptr->grp_nodes))) { - job_desc->max_nodes = qos_ptr->grp_nodes; + if (((*limit_set_max_nodes) == ADMIN_SET_LIMIT) + || (qos_ptr->grp_nodes == INFINITE) + || (update_call && (job_desc->max_nodes == NO_VAL))) { + /* no need to check/set */ + } else if ((job_desc->min_nodes != NO_VAL) + && (job_desc->min_nodes > qos_ptr->grp_nodes)) { + info("job submit for user %s(%u): " + "min node request %u exceeds " + "group max node limit %u for qos '%s'", + user_name, + job_desc->user_id, + job_desc->min_nodes, + qos_ptr->grp_nodes, + qos_ptr->name); + rc = false; + goto end_it; + } else if ((job_desc->max_nodes == 0) + || ((*limit_set_max_nodes) + && (job_desc->max_nodes > qos_ptr->grp_nodes))) { + job_desc->max_nodes = qos_ptr->grp_nodes; + (*limit_set_max_nodes) = 1; + } else if (job_desc->max_nodes > qos_ptr->grp_nodes) { + info("job submit for user %s(%u): " + "max node changed %u -> %u because " + "of qos limit", + user_name, + job_desc->user_id, + job_desc->max_nodes, + qos_ptr->grp_nodes); + if (job_desc->max_nodes == NO_VAL) (*limit_set_max_nodes) = 1; - } else if (job_desc->max_nodes > - qos_ptr->grp_nodes) { - info("job submit for user %s(%u): " - "max node changed %u -> %u because " - "of qos limit", - user_name, - job_desc->user_id, - job_desc->max_nodes, - qos_ptr->grp_nodes); - if(job_desc->max_nodes == NO_VAL) - (*limit_set_max_nodes) = 1; - job_desc->max_nodes = qos_ptr->grp_nodes; - } + job_desc->max_nodes = qos_ptr->grp_nodes; } if ((qos_ptr->grp_submit_jobs != INFINITE) && @@ -415,90 +415,92 @@ extern bool acct_policy_validate(job_desc_msg_t *job_desc, * job is running. */ - if (((*limit_set_max_cpus) != ADMIN_SET_LIMIT) - && (qos_ptr->max_cpus_pj != INFINITE)) { - if (job_desc->min_cpus > qos_ptr->max_cpus_pj) { - info("job submit for user %s(%u): " - "min cpu limit %u exceeds " - "qos max %u", - user_name, - job_desc->user_id, - job_desc->min_cpus, - qos_ptr->max_cpus_pj); - rc = false; - goto end_it; - } else if (job_desc->max_cpus == NO_VAL - || ((*limit_set_max_cpus) - && (job_desc->max_cpus - > qos_ptr->max_cpus_pj))) { - job_desc->max_cpus = qos_ptr->max_cpus_pj; + if (((*limit_set_max_cpus) == ADMIN_SET_LIMIT) + || (qos_ptr->max_cpus_pj == INFINITE) + || (update_call && (job_desc->max_cpus == NO_VAL))) { + /* no need to check/set */ + } else if ((job_desc->min_cpus != NO_VAL) + && (job_desc->min_cpus > qos_ptr->max_cpus_pj)) { + info("job submit for user %s(%u): " + "min cpu limit %u exceeds " + "qos max %u", + user_name, + job_desc->user_id, + job_desc->min_cpus, + qos_ptr->max_cpus_pj); + rc = false; + goto end_it; + } else if ((job_desc->max_cpus == NO_VAL) + || ((*limit_set_max_cpus) + && (job_desc->max_cpus + > qos_ptr->max_cpus_pj))) { + job_desc->max_cpus = qos_ptr->max_cpus_pj; + (*limit_set_max_cpus) = 1; + } else if (job_desc->max_cpus > qos_ptr->max_cpus_pj) { + info("job submit for user %s(%u): " + "max cpu changed %u -> %u because " + "of qos limit", + user_name, + job_desc->user_id, + job_desc->max_cpus, + qos_ptr->max_cpus_pj); + if (job_desc->max_cpus == NO_VAL) (*limit_set_max_cpus) = 1; - } else if (job_desc->max_cpus > - qos_ptr->max_cpus_pj) { - info("job submit for user %s(%u): " - "max cpu changed %u -> %u because " - "of qos limit", - user_name, - job_desc->user_id, - job_desc->max_cpus, - qos_ptr->max_cpus_pj); - if(job_desc->max_cpus == NO_VAL) - (*limit_set_max_cpus) = 1; - job_desc->max_cpus = qos_ptr->max_cpus_pj; - } + job_desc->max_cpus = qos_ptr->max_cpus_pj; } /* for validation we don't need to look at * qos_ptr->max_jobs. */ - if (((*limit_set_max_nodes) != ADMIN_SET_LIMIT) - && (qos_ptr->max_nodes_pj != INFINITE)) { - if (job_desc->min_nodes > qos_ptr->max_nodes_pj) { - info("job submit for user %s(%u): " - "min node limit %u exceeds " - "qos max %u", - user_name, - job_desc->user_id, - job_desc->min_nodes, - qos_ptr->max_nodes_pj); - rc = false; - goto end_it; - } else if (job_desc->max_nodes == 0 - || ((*limit_set_max_nodes) - && (job_desc->max_nodes - > qos_ptr->max_nodes_pj))) { - job_desc->max_nodes = qos_ptr->max_nodes_pj; + if (((*limit_set_max_nodes) == ADMIN_SET_LIMIT) + || (qos_ptr->max_nodes_pj == INFINITE) + || (update_call && (job_desc->max_nodes == NO_VAL))) { + /* no need to check/set */ + } else if ((job_desc->min_nodes != NO_VAL) + && (job_desc->min_nodes > qos_ptr->max_nodes_pj)) { + info("job submit for user %s(%u): " + "min node limit %u exceeds " + "qos max %u", + user_name, + job_desc->user_id, + job_desc->min_nodes, + qos_ptr->max_nodes_pj); + rc = false; + goto end_it; + } else if ((job_desc->max_nodes == 0) + || ((*limit_set_max_nodes) + && (job_desc->max_nodes + > qos_ptr->max_nodes_pj))) { + job_desc->max_nodes = qos_ptr->max_nodes_pj; + (*limit_set_max_nodes) = 1; + } else if (job_desc->max_nodes > qos_ptr->max_nodes_pj) { + info("job submit for user %s(%u): " + "max node changed %u -> %u because " + "of qos limit", + user_name, + job_desc->user_id, + job_desc->max_nodes, + qos_ptr->max_nodes_pj); + if (job_desc->max_nodes == NO_VAL) (*limit_set_max_nodes) = 1; - } else if (job_desc->max_nodes > - qos_ptr->max_nodes_pj) { - info("job submit for user %s(%u): " - "max node changed %u -> %u because " - "of qos limit", - user_name, - job_desc->user_id, - job_desc->max_nodes, - qos_ptr->max_nodes_pj); - if(job_desc->max_nodes == NO_VAL) - (*limit_set_max_nodes) = 1; - job_desc->max_nodes = qos_ptr->max_nodes_pj; - } + job_desc->max_nodes = qos_ptr->max_nodes_pj; } if (qos_ptr->max_submit_jobs_pu != INFINITE) { slurmdb_used_limits_t *used_limits = NULL; - if(qos_ptr->usage->user_limit_list) { + if (qos_ptr->usage->user_limit_list) { ListIterator itr = list_iterator_create( qos_ptr->usage->user_limit_list); while((used_limits = list_next(itr))) { - if(used_limits->uid - == job_desc->user_id) + if (used_limits->uid + == job_desc->user_id) break; } list_iterator_destroy(itr); } - if(used_limits && (used_limits->submit_jobs - >= qos_ptr->max_submit_jobs_pu)) { + if (used_limits && (used_limits->submit_jobs + >= qos_ptr->max_submit_jobs_pu)) { info("job submit for user %s(%u): " "qos max submit job limit exceeded %u", user_name, @@ -509,8 +511,11 @@ extern bool acct_policy_validate(job_desc_msg_t *job_desc, } } - if (((*limit_set_time) != ADMIN_SET_LIMIT) - && (qos_ptr->max_wall_pj != INFINITE)) { + if (((*limit_set_time) == ADMIN_SET_LIMIT) + || (qos_ptr->max_wall_pj == INFINITE) + || (update_call && (job_desc->time_limit == NO_VAL))) { + /* no need to check/set */ + } else { time_limit = qos_ptr->max_wall_pj; if (job_desc->time_limit == NO_VAL) { if (part_ptr->max_time == INFINITE) @@ -541,79 +546,79 @@ extern bool acct_policy_validate(job_desc_msg_t *job_desc, * assoc_ptr->grp_cpu_mins. */ - if (((*limit_set_max_cpus) != ADMIN_SET_LIMIT) - && (!qos_ptr || - (qos_ptr && qos_ptr->grp_cpus == INFINITE)) - && (assoc_ptr->grp_cpus != INFINITE)) { - if (job_desc->min_cpus > assoc_ptr->grp_cpus) { - info("job submit for user %s(%u): " - "min cpu request %u exceeds " - "group max cpu limit %u for account %s", - user_name, - job_desc->user_id, - job_desc->min_cpus, - assoc_ptr->grp_cpus, - assoc_ptr->acct); - rc = false; - break; - } else if (job_desc->max_cpus == NO_VAL - || ((*limit_set_max_cpus) - && (job_desc->max_cpus - > assoc_ptr->grp_cpus))) { - job_desc->max_cpus = assoc_ptr->grp_cpus; + if (((*limit_set_max_cpus) == ADMIN_SET_LIMIT) + || (qos_ptr && (qos_ptr->grp_cpus != INFINITE)) + || (assoc_ptr->grp_cpus == INFINITE) + || (update_call && (job_desc->max_cpus == NO_VAL))) { + /* no need to check/set */ + } else if ((job_desc->min_cpus != NO_VAL) + && (job_desc->min_cpus > assoc_ptr->grp_cpus)) { + info("job submit for user %s(%u): " + "min cpu request %u exceeds " + "group max cpu limit %u for account %s", + user_name, + job_desc->user_id, + job_desc->min_cpus, + assoc_ptr->grp_cpus, + assoc_ptr->acct); + rc = false; + break; + } else if ((job_desc->max_cpus == NO_VAL) + || ((*limit_set_max_cpus) + && (job_desc->max_cpus > assoc_ptr->grp_cpus))) { + job_desc->max_cpus = assoc_ptr->grp_cpus; + (*limit_set_max_cpus) = 1; + } else if (job_desc->max_cpus > assoc_ptr->grp_cpus) { + info("job submit for user %s(%u): " + "max cpu changed %u -> %u because " + "of account limit", + user_name, + job_desc->user_id, + job_desc->max_cpus, + assoc_ptr->grp_cpus); + if (job_desc->max_cpus == NO_VAL) (*limit_set_max_cpus) = 1; - } else if (job_desc->max_cpus > assoc_ptr->grp_cpus) { - info("job submit for user %s(%u): " - "max cpu changed %u -> %u because " - "of account limit", - user_name, - job_desc->user_id, - job_desc->max_cpus, - assoc_ptr->grp_cpus); - if(job_desc->max_cpus == NO_VAL) - (*limit_set_max_cpus) = 1; - job_desc->max_cpus = assoc_ptr->grp_cpus; - } + job_desc->max_cpus = assoc_ptr->grp_cpus; } /* for validation we don't need to look at * assoc_ptr->grp_jobs. */ - if (((*limit_set_max_nodes) != ADMIN_SET_LIMIT) - && (!qos_ptr || - (qos_ptr && qos_ptr->grp_nodes == INFINITE)) - && (assoc_ptr->grp_nodes != INFINITE)) { - if (job_desc->min_nodes > assoc_ptr->grp_nodes) { - info("job submit for user %s(%u): " - "min node request %u exceeds " - "group max node limit %u for account %s", - user_name, - job_desc->user_id, - job_desc->min_nodes, - assoc_ptr->grp_nodes, - assoc_ptr->acct); - rc = false; - break; - } else if (job_desc->max_nodes == 0 - || ((*limit_set_max_nodes) - && (job_desc->max_nodes - > assoc_ptr->grp_nodes))) { - job_desc->max_nodes = assoc_ptr->grp_nodes; + if (((*limit_set_max_nodes) == ADMIN_SET_LIMIT) + || (qos_ptr && (qos_ptr->grp_nodes != INFINITE)) + || (assoc_ptr->grp_nodes == INFINITE) + || (update_call && (job_desc->max_nodes == NO_VAL))) { + /* no need to check/set */ + } else if ((job_desc->min_nodes != NO_VAL) + && (job_desc->min_nodes > assoc_ptr->grp_nodes)) { + info("job submit for user %s(%u): " + "min node request %u exceeds " + "group max node limit %u for account %s", + user_name, + job_desc->user_id, + job_desc->min_nodes, + assoc_ptr->grp_nodes, + assoc_ptr->acct); + rc = false; + break; + } else if ((job_desc->max_nodes == 0) + || ((*limit_set_max_nodes) + && (job_desc->max_nodes + > assoc_ptr->grp_nodes))) { + job_desc->max_nodes = assoc_ptr->grp_nodes; + (*limit_set_max_nodes) = 1; + } else if (job_desc->max_nodes > assoc_ptr->grp_nodes) { + info("job submit for user %s(%u): " + "max node changed %u -> %u because " + "of account limit", + user_name, + job_desc->user_id, + job_desc->max_nodes, + assoc_ptr->grp_nodes); + if (job_desc->max_nodes == NO_VAL) (*limit_set_max_nodes) = 1; - } else if (job_desc->max_nodes > - assoc_ptr->grp_nodes) { - info("job submit for user %s(%u): " - "max node changed %u -> %u because " - "of account limit", - user_name, - job_desc->user_id, - job_desc->max_nodes, - assoc_ptr->grp_nodes); - if(job_desc->max_nodes == NO_VAL) - (*limit_set_max_nodes) = 1; - job_desc->max_nodes = assoc_ptr->grp_nodes; - } + job_desc->max_nodes = assoc_ptr->grp_nodes; } if ((!qos_ptr || @@ -650,78 +655,79 @@ extern bool acct_policy_validate(job_desc_msg_t *job_desc, * assoc_ptr->max_cpu_mins_pj. */ - if (((*limit_set_max_cpus) != ADMIN_SET_LIMIT) - && (!qos_ptr || - (qos_ptr && qos_ptr->max_cpus_pj == INFINITE)) - && (assoc_ptr->max_cpus_pj != INFINITE)) { - if (job_desc->min_cpus > assoc_ptr->max_cpus_pj) { - info("job submit for user %s(%u): " - "min cpu limit %u exceeds " - "account max %u", - user_name, - job_desc->user_id, - job_desc->min_cpus, - assoc_ptr->max_cpus_pj); - rc = false; - break; - } else if (job_desc->max_cpus == NO_VAL - || ((*limit_set_max_cpus) - && (job_desc->max_cpus - > assoc_ptr->max_cpus_pj))) { - job_desc->max_cpus = assoc_ptr->max_cpus_pj; + if (((*limit_set_max_cpus) == ADMIN_SET_LIMIT) + || (qos_ptr && (qos_ptr->max_cpus_pj != INFINITE)) + || (assoc_ptr->max_cpus_pj == INFINITE) + || (update_call && (job_desc->max_cpus == NO_VAL))) { + /* no need to check/set */ + } else if ((job_desc->min_cpus != NO_VAL) + && (job_desc->min_cpus > assoc_ptr->max_cpus_pj)) { + info("job submit for user %s(%u): " + "min cpu limit %u exceeds " + "account max %u", + user_name, + job_desc->user_id, + job_desc->min_cpus, + assoc_ptr->max_cpus_pj); + rc = false; + break; + } else if (job_desc->max_cpus == NO_VAL + || ((*limit_set_max_cpus) + && (job_desc->max_cpus + > assoc_ptr->max_cpus_pj))) { + job_desc->max_cpus = assoc_ptr->max_cpus_pj; + (*limit_set_max_cpus) = 1; + } else if (job_desc->max_cpus > assoc_ptr->max_cpus_pj) { + info("job submit for user %s(%u): " + "max cpu changed %u -> %u because " + "of account limit", + user_name, + job_desc->user_id, + job_desc->max_cpus, + assoc_ptr->max_cpus_pj); + if (job_desc->max_cpus == NO_VAL) (*limit_set_max_cpus) = 1; - } else if (job_desc->max_cpus > - assoc_ptr->max_cpus_pj) { - info("job submit for user %s(%u): " - "max cpu changed %u -> %u because " - "of account limit", - user_name, - job_desc->user_id, - job_desc->max_cpus, - assoc_ptr->max_cpus_pj); - if(job_desc->max_cpus == NO_VAL) - (*limit_set_max_cpus) = 1; - job_desc->max_cpus = assoc_ptr->max_cpus_pj; - } + job_desc->max_cpus = assoc_ptr->max_cpus_pj; } /* for validation we don't need to look at * assoc_ptr->max_jobs. */ - if (((*limit_set_max_nodes) != ADMIN_SET_LIMIT) - && (!qos_ptr || - (qos_ptr && qos_ptr->max_nodes_pj == INFINITE)) - && (assoc_ptr->max_nodes_pj != INFINITE)) { - if (job_desc->min_nodes > assoc_ptr->max_nodes_pj) { - info("job submit for user %s(%u): " - "min node limit %u exceeds " - "account max %u", - user_name, - job_desc->user_id, - job_desc->min_nodes, - assoc_ptr->max_nodes_pj); - rc = false; - break; - } else if (job_desc->max_nodes == 0 - || ((*limit_set_max_nodes) - && (job_desc->max_nodes - > assoc_ptr->max_nodes_pj))) { - job_desc->max_nodes = assoc_ptr->max_nodes_pj; + if (((*limit_set_max_nodes) == ADMIN_SET_LIMIT) + || (qos_ptr && (qos_ptr->max_nodes_pj != INFINITE)) + || (assoc_ptr->max_nodes_pj == INFINITE) + || (update_call && (job_desc->max_nodes == NO_VAL))) { + /* no need to check/set */ + } else if ((job_desc->min_nodes != NO_VAL) + && (job_desc->min_nodes > assoc_ptr->max_nodes_pj)) { + info("job submit for user %s(%u): " + "min node limit %u exceeds " + "account max %u", + user_name, + job_desc->user_id, + job_desc->min_nodes, + assoc_ptr->max_nodes_pj); + rc = false; + break; + } else if (((job_desc->max_nodes == NO_VAL) + || (job_desc->max_nodes == 0)) + || ((*limit_set_max_nodes) + && (job_desc->max_nodes + > assoc_ptr->max_nodes_pj))) { + job_desc->max_nodes = assoc_ptr->max_nodes_pj; + (*limit_set_max_nodes) = 1; + } else if (job_desc->max_nodes > assoc_ptr->max_nodes_pj) { + info("job submit for user %s(%u): " + "max node changed %u -> %u because " + "of account limit", + user_name, + job_desc->user_id, + job_desc->max_nodes, + assoc_ptr->max_nodes_pj); + if (job_desc->max_nodes == NO_VAL) (*limit_set_max_nodes) = 1; - } else if (job_desc->max_nodes > - assoc_ptr->max_nodes_pj) { - info("job submit for user %s(%u): " - "max node changed %u -> %u because " - "of account limit", - user_name, - job_desc->user_id, - job_desc->max_nodes, - assoc_ptr->max_nodes_pj); - if(job_desc->max_nodes == NO_VAL) - (*limit_set_max_nodes) = 1; - job_desc->max_nodes = assoc_ptr->max_nodes_pj; - } + job_desc->max_nodes = assoc_ptr->max_nodes_pj; } if ((!qos_ptr || @@ -738,10 +744,12 @@ extern bool acct_policy_validate(job_desc_msg_t *job_desc, break; } - if (((*limit_set_time) != ADMIN_SET_LIMIT) - && (!qos_ptr || - (qos_ptr && qos_ptr->max_wall_pj == INFINITE)) - && (assoc_ptr->max_wall_pj != INFINITE)) { + if (((*limit_set_time) == ADMIN_SET_LIMIT) + || (qos_ptr && (qos_ptr->max_wall_pj != INFINITE)) + || (assoc_ptr->max_wall_pj == INFINITE) + || (update_call && (job_desc->time_limit == NO_VAL))) { + /* no need to check/set */ + } else { time_limit = assoc_ptr->max_wall_pj; if (job_desc->time_limit == NO_VAL) { if (part_ptr->max_time == INFINITE) @@ -1359,7 +1367,7 @@ extern int acct_policy_update_pending_job(struct job_record *job_ptr) job_ptr->assoc_ptr, job_ptr->qos_ptr, &limit_set_max_cpus, &limit_set_max_nodes, - &limit_set_time)) { + &limit_set_time, 0)) { info("acct_policy_update_pending_job: exceeded " "association/qos's cpu, node or " "time limit for job %d", job_ptr->job_id); diff --git a/src/slurmctld/acct_policy.h b/src/slurmctld/acct_policy.h index 580506201..3a1d9993c 100644 --- a/src/slurmctld/acct_policy.h +++ b/src/slurmctld/acct_policy.h @@ -72,7 +72,7 @@ extern bool acct_policy_validate(job_desc_msg_t *job_desc, slurmdb_qos_rec_t *qos_ptr, uint16_t *limit_set_max_cpus, uint16_t *limit_set_max_nodes, - uint16_t *limit_set_time); + uint16_t *limit_set_time, bool update_call); /* * acct_policy_job_runnable - Determine of the specified job can execute * right now or not depending upon accounting policy (e.g. running diff --git a/src/slurmctld/controller.c b/src/slurmctld/controller.c index 603845141..7338c2172 100644 --- a/src/slurmctld/controller.c +++ b/src/slurmctld/controller.c @@ -668,6 +668,7 @@ int main(int argc, char *argv[]) switch_fini(); /* purge remaining data structures */ + license_free(); slurm_cred_ctx_destroy(slurmctld_config.cred_ctx); slurm_crypto_fini(); /* must be after ctx_destroy */ slurm_conf_destroy(); diff --git a/src/slurmctld/gang.c b/src/slurmctld/gang.c index d8af1351e..a9678799a 100644 --- a/src/slurmctld/gang.c +++ b/src/slurmctld/gang.c @@ -799,9 +799,11 @@ static void _update_active_row(struct gs_part *p_ptr, int add_new_jobs) /* this job has been preempted by a shadow job. * suspend it and preserve it's job_list order */ if (j_ptr->sig_state != GS_SUSPEND) { - if (p_ptr->num_shadows) + if (p_ptr->num_shadows && + (slurm_job_preempt_mode(j_ptr->job_ptr) != + PREEMPT_MODE_SUSPEND)) { _preempt_job_queue(j_ptr->job_id); - else + } else _suspend_job(j_ptr->job_id); j_ptr->sig_state = GS_SUSPEND; _clear_shadow(j_ptr); @@ -821,9 +823,11 @@ static void _update_active_row(struct gs_part *p_ptr, int add_new_jobs) /* this job has been preempted by a shadow job. * suspend it and preserve it's job_list order */ if (j_ptr->sig_state != GS_SUSPEND) { - if (p_ptr->num_shadows) + if (p_ptr->num_shadows && + (slurm_job_preempt_mode(j_ptr->job_ptr) != + PREEMPT_MODE_SUSPEND)) { _preempt_job_queue(j_ptr->job_id); - else + } else _suspend_job(j_ptr->job_id); j_ptr->sig_state = GS_SUSPEND; _clear_shadow(j_ptr); @@ -1011,9 +1015,11 @@ static uint16_t _add_job_to_part(struct gs_part *p_ptr, info("gang: _add_job_to_part: suspending job %u", job_ptr->job_id); } - if (p_ptr->num_shadows) + if (p_ptr->num_shadows && + (slurm_job_preempt_mode(job_ptr) != + PREEMPT_MODE_SUSPEND)) { _preempt_job_queue(job_ptr->job_id); - else + } else _suspend_job(job_ptr->job_id); j_ptr->sig_state = GS_SUSPEND; } @@ -1517,9 +1523,11 @@ static void _cycle_job_list(struct gs_part *p_ptr) info("gang: _cycle_job_list: suspending job %u", j_ptr->job_id); } - if (p_ptr->num_shadows) + if (p_ptr->num_shadows && + (slurm_job_preempt_mode(j_ptr->job_ptr) != + PREEMPT_MODE_SUSPEND)) { _preempt_job_queue(j_ptr->job_id); - else + } else _suspend_job(j_ptr->job_id); j_ptr->sig_state = GS_SUSPEND; _clear_shadow(j_ptr); diff --git a/src/slurmctld/job_mgr.c b/src/slurmctld/job_mgr.c index 578cf1bcf..ad7679887 100644 --- a/src/slurmctld/job_mgr.c +++ b/src/slurmctld/job_mgr.c @@ -252,7 +252,8 @@ void delete_job_details(struct job_record *job_entry) return; xassert (job_entry->details->magic == DETAILS_MAGIC); - _delete_job_desc_files(job_entry->job_id); + if (IS_JOB_FINISHED(job_entry)) + _delete_job_desc_files(job_entry->job_id); for (i=0; i<job_entry->details->argc; i++) xfree(job_entry->details->argv[i]); @@ -1893,7 +1894,6 @@ extern int kill_running_job_by_node_name(char *node_name) info("requeue job %u due to failure of node %s", job_ptr->job_id, node_name); - _set_job_prio(job_ptr); snprintf(requeue_msg, sizeof(requeue_msg), "Job requeued due to failure " "of node %s", @@ -3192,7 +3192,7 @@ static int _job_create(job_desc_msg_t * job_desc, int allocate, int will_run, assoc_ptr, qos_ptr, &limit_set_max_cpus, &limit_set_max_nodes, - &limit_set_time))) { + &limit_set_time, 0))) { info("_job_create: exceeded association's node or time limit " "for user %u", job_desc->user_id); error_code = ESLURM_ACCOUNTING_POLICY; @@ -4632,8 +4632,7 @@ static void _list_delete_job(void *job_entry) fatal("job hash error"); *job_pptr = job_ptr->job_next; - if (IS_JOB_FINISHED(job_ptr)) - delete_job_details(job_ptr); + delete_job_details(job_ptr); xfree(job_ptr->account); xfree(job_ptr->alloc_node); xfree(job_ptr->comment); @@ -5908,7 +5907,7 @@ int update_job(job_desc_msg_t * job_specs, uid_t uid) job_ptr->assoc_ptr, job_ptr->qos_ptr, &limit_set_max_cpus, &limit_set_max_nodes, - &limit_set_time)) { + &limit_set_time, 1)) { info("update_job: exceeded association's cpu, node or " "time limit for user %u", job_specs->user_id); error_code = ESLURM_ACCOUNTING_POLICY; @@ -6279,7 +6278,7 @@ int update_job(job_desc_msg_t * job_specs, uid_t uid) else if (job_ptr->priority == job_specs->priority) { debug("update_job: setting priority to current value"); if ((job_ptr->priority == 0) && authorized) { - if (job_specs->alloc_sid & ALLOC_SID_USER_HOLD) + if (job_specs->alloc_sid == ALLOC_SID_USER_HOLD) job_ptr->state_reason = WAIT_HELD_USER; else job_ptr->state_reason = WAIT_HELD; @@ -6300,12 +6299,16 @@ int update_job(job_desc_msg_t * job_specs, uid_t uid) update_accounting = true; if (job_ptr->priority == 0) { if (authorized && - ((job_specs->alloc_sid & - ALLOC_SID_USER_HOLD) == 0)) { + (job_specs->alloc_sid != + ALLOC_SID_USER_HOLD)) { job_ptr->state_reason = WAIT_HELD; } else job_ptr->state_reason = WAIT_HELD_USER; xfree(job_ptr->state_desc); + } else if ((job_ptr->state_reason == WAIT_HELD) || + (job_ptr->state_reason == WAIT_HELD_USER)) { + job_ptr->state_reason = WAIT_NO_REASON; + xfree(job_ptr->state_desc); } } else if ((job_ptr->priority == 0) && (job_ptr->state_reason == WAIT_HELD_USER)) { @@ -6676,7 +6679,7 @@ int update_job(job_desc_msg_t * job_specs, uid_t uid) job_specs->min_nodes, job_specs->job_id); error_code = ESLURM_INVALID_NODE_COUNT; goto fini; - } else if (job_specs->min_nodes > job_ptr->node_cnt) { + } else if (job_specs->min_nodes == job_ptr->node_cnt) { debug2("No change in node count update for job %u", job_specs->job_id); } else { @@ -7766,6 +7769,7 @@ extern bool job_independent(struct job_record *job_ptr, int will_run) xfree(job_ptr->state_desc); job_ptr->start_time = now; job_ptr->end_time = now; + srun_allocate_abort(job_ptr); job_completion_logger(job_ptr, false); return false; } @@ -7787,7 +7791,8 @@ extern bool job_independent(struct job_record *job_ptr, int will_run) job_ptr->state_reason = WAIT_NO_REASON; xfree(job_ptr->state_desc); } - if (detail_ptr && (detail_ptr->begin_time == 0)) { + if ((detail_ptr && (detail_ptr->begin_time == 0) && + (job_ptr->priority != 0))) { detail_ptr->begin_time = now; } else if (job_ptr->state_reason == WAIT_TIME) { job_ptr->state_reason = WAIT_NO_REASON; @@ -8099,7 +8104,6 @@ extern int job_suspend(suspend_msg_t *sus_ptr, uid_t uid, goto reply; _suspend_job(job_ptr, sus_ptr->op); job_ptr->job_state = JOB_RUNNING; - _set_job_prio(job_ptr); job_ptr->tot_sus_time += difftime(now, job_ptr->suspend_time); if (!wiki_sched_test) { @@ -8201,8 +8205,6 @@ extern int job_requeue (uid_t uid, uint32_t job_id, slurm_fd_t conn_fd, goto reply; } - /* reset the priority */ - _set_job_prio(job_ptr); slurm_sched_requeue(job_ptr, "Job requeued by user/admin"); last_job_update = now; diff --git a/src/slurmctld/job_scheduler.c b/src/slurmctld/job_scheduler.c index 44673583d..936509716 100644 --- a/src/slurmctld/job_scheduler.c +++ b/src/slurmctld/job_scheduler.c @@ -138,15 +138,17 @@ static void _job_queue_rec_del(void *x) /* * build_job_queue - build (non-priority ordered) list of pending jobs + * IN clear_start - if set then clear the start_time for pending jobs * RET the job queue * NOTE: the caller must call list_destroy() on RET value to free memory */ -extern List build_job_queue(void) +extern List build_job_queue(bool clear_start) { List job_queue; ListIterator job_iterator, part_iterator; struct job_record *job_ptr = NULL; struct part_record *part_ptr; + bool job_is_pending; job_queue = list_create(_job_queue_rec_del); if (job_queue == NULL) @@ -156,8 +158,11 @@ extern List build_job_queue(void) fatal("list_iterator_create memory allocation failure"); while ((job_ptr = (struct job_record *) list_next(job_iterator))) { xassert (job_ptr->magic == JOB_MAGIC); - if ((!IS_JOB_PENDING(job_ptr)) || IS_JOB_COMPLETING(job_ptr)) + job_is_pending = IS_JOB_PENDING(job_ptr); + if (!job_is_pending || IS_JOB_COMPLETING(job_ptr)) continue; + if (job_is_pending && clear_start) + job_ptr->start_time = (time_t) 0; if (job_ptr->priority == 0) { /* held */ if ((job_ptr->state_reason != WAIT_HELD) && (job_ptr->state_reason != WAIT_HELD_USER)) { @@ -384,7 +389,7 @@ extern int schedule(uint32_t job_limit) save_avail_node_bitmap = bit_copy(avail_node_bitmap); debug("sched: Running job scheduler"); - job_queue = build_job_queue(); + job_queue = build_job_queue(false); while ((job_queue_rec = list_pop_bottom(job_queue, sort_job_queue2))) { job_ptr = job_queue_rec->job_ptr; part_ptr = job_queue_rec->part_ptr; @@ -416,8 +421,10 @@ extern int schedule(uint32_t job_limit) if ((job_ptr->resv_name == NULL) && _failed_partition(job_ptr->part_ptr, failed_parts, failed_part_cnt)) { - job_ptr->state_reason = WAIT_PRIORITY; - xfree(job_ptr->state_desc); + if (job_ptr->priority != 1) { /* not system hold */ + job_ptr->state_reason = WAIT_PRIORITY; + xfree(job_ptr->state_desc); + } debug3("sched: JobId=%u. State=%s. Reason=%s. " "Priority=%u. Partition=%s.", job_ptr->job_id, @@ -598,12 +605,20 @@ extern int sort_job_queue2(void *x, void *y) { job_queue_rec_t *job_rec1 = (job_queue_rec_t *) x; job_queue_rec_t *job_rec2 = (job_queue_rec_t *) y; + bool has_resv1, has_resv2; if (slurm_job_preempt_check(job_rec1, job_rec2)) return -1; if (slurm_job_preempt_check(job_rec2, job_rec1)) return 1; + has_resv1 = (job_rec1->job_ptr->resv_id != 0); + has_resv2 = (job_rec2->job_ptr->resv_id != 0); + if (has_resv1 && !has_resv2) + return -1; + if (!has_resv1 && has_resv2) + return 1; + if (job_rec1->job_ptr->priority < job_rec2->job_ptr->priority) return 1; if (job_rec1->job_ptr->priority > job_rec2->job_ptr->priority) @@ -1274,6 +1289,19 @@ static char **_build_env(struct job_record *job_ptr) select_g_select_jobinfo_get(job_ptr->select_jobinfo, SELECT_JOBDATA_BLOCK_ID, &name); setenvf(&my_env, "MPIRUN_PARTITION", "%s", name); +# ifdef HAVE_BGP + { + uint16_t conn_type = (uint16_t)NO_VAL; + select_g_select_jobinfo_get(job_ptr->select_jobinfo, + SELECT_JOBDATA_CONN_TYPE, + &conn_type); + if (conn_type > SELECT_SMALL) { + /* SUBMIT_POOL over rides + HTC_SUBMIT_POOL */ + setenvf(&my_env, "SUBMIT_POOL", "%s", name); + } + } +# endif xfree(name); #endif setenvf(&my_env, "SLURM_JOB_ACCOUNT", "%s", job_ptr->account); diff --git a/src/slurmctld/job_scheduler.h b/src/slurmctld/job_scheduler.h index dbc27302d..2b968cc1a 100644 --- a/src/slurmctld/job_scheduler.h +++ b/src/slurmctld/job_scheduler.h @@ -59,10 +59,11 @@ extern int build_feature_list(struct job_record *job_ptr); /* * build_job_queue - build (non-priority ordered) list of pending jobs + * IN clear_start - if set then clear the start_time for pending jobs * RET the job queue * NOTE: the caller must call list_destroy() on RET value to free memory */ -extern List build_job_queue(void); +extern List build_job_queue(bool clear_start); /* * epilog_slurmctld - execute the prolog_slurmctld for a job that has just diff --git a/src/slurmctld/node_mgr.c b/src/slurmctld/node_mgr.c index 9b87f7fc5..166f0903b 100644 --- a/src/slurmctld/node_mgr.c +++ b/src/slurmctld/node_mgr.c @@ -1508,23 +1508,25 @@ extern int validate_node_specs(slurm_node_registration_status_msg_t *reg_msg) threads2 = cores2 * config_ptr->threads; if (threads1 < threads2) { - error("Node %s has low socket*core*thread count %u", - reg_msg->node_name, threads1); + error("Node %s has low socket*core*thread count " + "(%d < %d)", + reg_msg->node_name, threads1, threads2); error_code = EINVAL; reason_down = "Low socket*core*thread count"; } else if ((slurmctld_conf.fast_schedule == 0) && ((cr_flag == 1) || gang_flag) && (cores1 < cores2)) { - error("Node %s has low socket*core count %u", - reg_msg->node_name, cores1); + error("Node %s has low socket*core count (%d < %d)", + reg_msg->node_name, cores1, cores2); error_code = EINVAL; reason_down = "Low socket*core count"; } else if ((slurmctld_conf.fast_schedule == 0) && ((cr_flag == 1) || gang_flag) && ((sockets1 > sockets2) || (cores1 > cores2) || (threads1 > threads2))) { - error("Node %s has high socket*core*thread count %u, " - "extra resources ignored", - reg_msg->node_name, threads1); + error("Node %s has high socket,core,thread count " + "(%d,%d,%d > %d,%d,%d), extra resources ignored", + reg_msg->node_name, sockets1, cores1, threads1, + sockets2, cores2, threads2); /* Preserve configured values */ reg_msg->sockets = config_ptr->sockets; reg_msg->cores = config_ptr->cores; @@ -1532,16 +1534,18 @@ extern int validate_node_specs(slurm_node_registration_status_msg_t *reg_msg) } if (reg_msg->cpus < config_ptr->cpus) { - error ("Node %s has low cpu count %u", - reg_msg->node_name, reg_msg->cpus); + error("Node %s has low cpu count (%u < %u)", + reg_msg->node_name, reg_msg->cpus, + config_ptr->cpus); error_code = EINVAL; reason_down = "Low CPUs"; } else if ((slurmctld_conf.fast_schedule == 0) && ((cr_flag == 1) || gang_flag) && (reg_msg->cpus > config_ptr->cpus)) { - error("Node %s has high CPU count %u, " + error("Node %s has high CPU count (%u > %u), " "extra resources ignored", - reg_msg->node_name, reg_msg->cpus); + reg_msg->node_name, reg_msg->cpus, + config_ptr->cpus); reg_msg->cpus = config_ptr->cpus; } } @@ -1563,8 +1567,9 @@ extern int validate_node_specs(slurm_node_registration_status_msg_t *reg_msg) if ((slurmctld_conf.fast_schedule != 2) && (reg_msg->real_memory < config_ptr->real_memory)) { - error ("Node %s has low real_memory size %u", - reg_msg->node_name, reg_msg->real_memory); + error("Node %s has low real_memory size (%u < %u)", + reg_msg->node_name, reg_msg->real_memory, + config_ptr->real_memory); error_code = EINVAL; reason_down = "Low RealMemory"; } @@ -1572,8 +1577,9 @@ extern int validate_node_specs(slurm_node_registration_status_msg_t *reg_msg) if ((slurmctld_conf.fast_schedule != 2) && (reg_msg->tmp_disk < config_ptr->tmp_disk)) { - error ("Node %s has low tmp_disk size %u", - reg_msg->node_name, reg_msg->tmp_disk); + error("Node %s has low tmp_disk size (%u < %u)", + reg_msg->node_name, reg_msg->tmp_disk, + config_ptr->tmp_disk); error_code = EINVAL; reason_down = "Low TmpDisk"; } @@ -2525,8 +2531,9 @@ void make_node_idle(struct node_record *node_ptr, (node_ptr->run_job_cnt == 0) && (node_ptr->comp_job_cnt == 0)) { node_ptr->node_state = NODE_STATE_IDLE | node_flags; - bit_set(idle_node_bitmap, inx); bit_clear(avail_node_bitmap, inx); + bit_set(idle_node_bitmap, inx); + bit_set(up_node_bitmap, inx); debug3("make_node_idle: Node %s is DRAINED", node_ptr->name); node_ptr->last_idle = now; @@ -2536,11 +2543,19 @@ void make_node_idle(struct node_record *node_ptr, slurm_get_slurm_user_id()); } else if (node_ptr->run_job_cnt) { node_ptr->node_state = NODE_STATE_ALLOCATED | node_flags; + if (!IS_NODE_NO_RESPOND(node_ptr) && + !IS_NODE_FAIL(node_ptr) && !IS_NODE_DRAIN(node_ptr)) + bit_set(avail_node_bitmap, inx); + bit_set(up_node_bitmap, inx); } else { node_ptr->node_state = NODE_STATE_IDLE | node_flags; + if (!IS_NODE_NO_RESPOND(node_ptr) && + !IS_NODE_FAIL(node_ptr) && !IS_NODE_DRAIN(node_ptr)) + bit_set(avail_node_bitmap, inx); if (!IS_NODE_NO_RESPOND(node_ptr) && !IS_NODE_COMPLETING(node_ptr)) bit_set(idle_node_bitmap, inx); + bit_set(up_node_bitmap, inx); node_ptr->last_idle = now; } } diff --git a/src/slurmctld/node_scheduler.c b/src/slurmctld/node_scheduler.c index 057bc3cdf..5f5da2888 100644 --- a/src/slurmctld/node_scheduler.c +++ b/src/slurmctld/node_scheduler.c @@ -731,6 +731,32 @@ _pick_best_nodes(struct node_set *node_set_ptr, int node_set_size, /* Accumulate resources for this job based upon its required * features (possibly with node counts). */ for (j = min_feature; j <= max_feature; j++) { + if (job_ptr->details->req_node_bitmap) { + bool missing_required_nodes = false; + for (i = 0; i < node_set_size; i++) { + if (!bit_test(node_set_ptr[i].feature_bits, j)) + continue; + if (avail_bitmap) { + bit_or(avail_bitmap, + node_set_ptr[i].my_bitmap); + } else { + avail_bitmap = bit_copy(node_set_ptr[i]. + my_bitmap); + if (avail_bitmap == NULL) + fatal("bit_copy malloc failure"); + } + } + if (!bit_super_set(job_ptr->details->req_node_bitmap, + avail_bitmap)) + missing_required_nodes = true; + FREE_NULL_BITMAP(avail_bitmap); + if (missing_required_nodes) + continue; + avail_bitmap = bit_copy(job_ptr->details-> + req_node_bitmap); + if (avail_bitmap == NULL) + fatal("bit_copy malloc failure"); + } for (i = 0; i < node_set_size; i++) { if (!bit_test(node_set_ptr[i].feature_bits, j)) continue; @@ -776,11 +802,10 @@ _pick_best_nodes(struct node_set *node_set_ptr, int node_set_size, } avail_nodes = bit_set_count(avail_bitmap); tried_sched = false; /* need to test these nodes */ - - if (((i+1) < node_set_size) && - (shared || preempt_flag || - (node_set_ptr[i].weight == - node_set_ptr[i+1].weight))) { + if ((shared || preempt_flag) && + ((i+1) < node_set_size) && + (node_set_ptr[i].weight == + node_set_ptr[i+1].weight)) { /* Keep accumulating so we can pick the * most lightly loaded nodes */ continue; @@ -792,11 +817,6 @@ _pick_best_nodes(struct node_set *node_set_ptr, int node_set_size, ((i+1) < node_set_size))) continue; /* Keep accumulating nodes */ - if ((job_ptr->details->req_node_bitmap) && - (!bit_super_set(job_ptr->details->req_node_bitmap, - avail_bitmap))) - continue; - /* NOTE: select_g_job_test() is destructive of * avail_bitmap, so save a backup copy */ backup_bitmap = bit_copy(avail_bitmap); diff --git a/src/slurmctld/reservation.c b/src/slurmctld/reservation.c index 151e49602..a9b45c991 100644 --- a/src/slurmctld/reservation.c +++ b/src/slurmctld/reservation.c @@ -90,6 +90,7 @@ uint32_t top_suffix = 0; uint32_t cnodes_per_bp = 0; #endif +static void _advance_resv_time(slurmctld_resv_t *resv_ptr); static void _advance_time(time_t *res_time, int day_cnt); static int _build_account_list(char *accounts, int *account_cnt, char ***account_list); @@ -2365,6 +2366,7 @@ static int _select_nodes(resv_desc_msg_t *resv_desc_ptr, bitstr_t *node_bitmap; ListIterator iter; int i, rc = SLURM_SUCCESS; + time_t now = time(NULL); if (*part_ptr == NULL) { *part_ptr = default_part_loc; @@ -2383,6 +2385,8 @@ static int _select_nodes(resv_desc_msg_t *resv_desc_ptr, if (!iter) fatal("malloc: list_iterator_create"); while ((resv_ptr = (slurmctld_resv_t *) list_next(iter))) { + if (resv_ptr->end_time <= now) + _advance_resv_time(resv_ptr); if ((resv_ptr->node_bitmap == NULL) || (resv_ptr->start_time >= resv_desc_ptr->end_time) || (resv_ptr->end_time <= resv_desc_ptr->start_time)) @@ -2675,6 +2679,8 @@ extern void job_time_adj_resv(struct job_record *job_ptr) if (!iter) fatal("malloc: list_iterator_create"); while ((resv_ptr = (slurmctld_resv_t *) list_next(iter))) { + if (resv_ptr->end_time <= now) + _advance_resv_time(resv_ptr); if ((job_ptr->resv_ptr == resv_ptr) || (resv_ptr->start_time <= now)) continue; /* authorized user of reservation */ @@ -2755,7 +2761,7 @@ extern int job_test_lic_resv(struct job_record *job_ptr, char *lic_name, time_t when) { slurmctld_resv_t * resv_ptr; - time_t job_start_time, job_end_time; + time_t job_start_time, job_end_time, now = time(NULL); ListIterator iter; int resv_cnt = 0; @@ -2765,6 +2771,8 @@ extern int job_test_lic_resv(struct job_record *job_ptr, char *lic_name, if (!iter) fatal("malloc: list_iterator_create"); while ((resv_ptr = (slurmctld_resv_t *) list_next(iter))) { + if (resv_ptr->end_time <= now) + _advance_resv_time(resv_ptr); if ((resv_ptr->start_time >= job_end_time) || (resv_ptr->end_time <= job_start_time)) continue; /* reservation at different time */ @@ -2802,6 +2810,7 @@ extern int job_test_resv(struct job_record *job_ptr, time_t *when, { slurmctld_resv_t * resv_ptr, *res2_ptr; time_t job_start_time, job_end_time, lic_resv_time; + time_t now = time(NULL); ListIterator iter; int i, rc = SLURM_SUCCESS; @@ -2818,6 +2827,8 @@ extern int job_test_resv(struct job_record *job_ptr, time_t *when, return ESLURM_RESERVATION_INVALID; if (_valid_job_access_resv(job_ptr, resv_ptr) != SLURM_SUCCESS) return ESLURM_RESERVATION_ACCESS; + if (resv_ptr->end_time <= now) + _advance_resv_time(resv_ptr); if (*when < resv_ptr->start_time) { /* reservation starts later */ *when = resv_ptr->start_time; @@ -2825,7 +2836,7 @@ extern int job_test_resv(struct job_record *job_ptr, time_t *when, } if (resv_ptr->node_cnt == 0) { /* empty reservation treated like it will start later */ - *when = time(NULL) + 600; + *when = now + 600; return ESLURM_INVALID_TIME_VALUE; } if (*when > resv_ptr->end_time) { @@ -2885,6 +2896,8 @@ extern int job_test_resv(struct job_record *job_ptr, time_t *when, if (!iter) fatal("malloc: list_iterator_create"); while ((resv_ptr = (slurmctld_resv_t *) list_next(iter))) { + if (resv_ptr->end_time <= now) + _advance_resv_time(resv_ptr); if ((resv_ptr->node_bitmap == NULL) || (resv_ptr->start_time >= job_end_time) || (resv_ptr->end_time <= job_start_time)) @@ -2989,6 +3002,35 @@ extern int job_resv_check(struct job_record *job_ptr) return SLURM_SUCCESS; } +/* Advance a expired reservation's time stamps one day or one week + * as appropriate. */ +static void _advance_resv_time(slurmctld_resv_t *resv_ptr) +{ + int day_cnt = 0; + char *interval = ""; + + if (resv_ptr->flags & RESERVE_FLAG_DAILY) { + day_cnt = 1; + interval = "day"; + } else if (resv_ptr->flags & RESERVE_FLAG_WEEKLY) { + day_cnt = 7; + interval = "week"; + } + + if (day_cnt) { + verbose("Advance reservation %s one %s", resv_ptr->name, + interval); + resv_ptr->start_time = resv_ptr->start_time_first; + _advance_time(&resv_ptr->start_time, day_cnt); + resv_ptr->start_time_prev = resv_ptr->start_time; + resv_ptr->start_time_first = resv_ptr->start_time; + _advance_time(&resv_ptr->end_time, day_cnt); + _post_resv_create(resv_ptr); + last_resv_update = time(NULL); + schedule_resv_save(); + } +} + /* Finish scan of all jobs for valid reservations * * Purge vestigial reservation records. @@ -3012,35 +3054,7 @@ extern void fini_job_resv_check(void) _validate_node_choice(resv_ptr); continue; } - - if ((resv_ptr->job_run_cnt == 0) && - (resv_ptr->flags & RESERVE_FLAG_DAILY)) { - verbose("Advance reservation %s one day", - resv_ptr->name); - resv_ptr->start_time = resv_ptr->start_time_first; - _advance_time(&resv_ptr->start_time, 1); - resv_ptr->start_time_prev = resv_ptr->start_time; - resv_ptr->start_time_first = resv_ptr->start_time; - _advance_time(&resv_ptr->end_time, 1); - _post_resv_create(resv_ptr); - last_resv_update = now; - schedule_resv_save(); - continue; - } - if ((resv_ptr->job_run_cnt == 0) && - (resv_ptr->flags & RESERVE_FLAG_WEEKLY)) { - verbose("Advance reservation %s one week", - resv_ptr->name); - resv_ptr->start_time = resv_ptr->start_time_first; - _advance_time(&resv_ptr->start_time, 7); - resv_ptr->start_time_prev = resv_ptr->start_time; - resv_ptr->start_time_first = resv_ptr->start_time; - _advance_time(&resv_ptr->end_time, 7); - _post_resv_create(resv_ptr); - last_resv_update = now; - schedule_resv_save(); - continue; - } + _advance_resv_time(resv_ptr); if ((resv_ptr->job_pend_cnt == 0) && (resv_ptr->job_run_cnt == 0) && (resv_ptr->maint_set_node == 0) && diff --git a/src/slurmctld/slurmctld.h b/src/slurmctld/slurmctld.h index 588b10452..96afd1db7 100644 --- a/src/slurmctld/slurmctld.h +++ b/src/slurmctld/slurmctld.h @@ -1527,7 +1527,7 @@ extern slurm_step_layout_t *step_layout_create(struct step_record *step_ptr, uint32_t num_tasks, uint16_t cpus_per_task, uint16_t task_dist, - uint32_t plane_size); + uint16_t plane_size); /* start_power_mgr - Start power management thread as needed. The thread * terminates automatically at slurmctld shutdown time. diff --git a/src/slurmctld/step_mgr.c b/src/slurmctld/step_mgr.c index ff834ac65..7948aa5ca 100644 --- a/src/slurmctld/step_mgr.c +++ b/src/slurmctld/step_mgr.c @@ -644,6 +644,23 @@ _pick_step_nodes (struct job_record *job_ptr, gres_cnt /= cpus_per_task; total_tasks = MIN(total_tasks, gres_cnt); + if (step_spec->plane_size != (uint16_t) NO_VAL) { + if (avail_tasks < step_spec->plane_size) + avail_tasks = 0; + else { + /* Round count down */ + avail_tasks /= step_spec->plane_size; + avail_tasks *= step_spec->plane_size; + } + if (total_tasks < step_spec->plane_size) + total_tasks = 0; + else { + /* Round count down */ + total_tasks /= step_spec->plane_size; + total_tasks *= step_spec->plane_size; + } + } + if (step_spec->max_nodes && (nodes_picked_cnt >= step_spec->max_nodes)) bit_clear(nodes_avail, i); @@ -1573,8 +1590,8 @@ step_create(job_step_create_request_msg_t *step_specs, step_specs->node_list = xstrdup(step_node_list); } if (slurm_get_debug_flags() & DEBUG_FLAG_STEPS) { - verbose("got %s and %s looking for %u nodes", step_node_list, - step_specs->node_list, step_specs->min_nodes); + verbose("Picked nodes %s when accumulating from %s", + step_node_list, step_specs->node_list); } step_ptr->step_node_bitmap = nodeset; @@ -1710,7 +1727,7 @@ extern slurm_step_layout_t *step_layout_create(struct step_record *step_ptr, uint32_t num_tasks, uint16_t cpus_per_task, uint16_t task_dist, - uint32_t plane_size) + uint16_t plane_size) { uint16_t cpus_per_node[node_count]; uint32_t cpu_count_reps[node_count], gres_cpus; @@ -2257,8 +2274,9 @@ extern int step_partial_comp(step_complete_msg_t *req, uid_t uid, return SLURM_SUCCESS; } if (req->range_last < req->range_first) { - error("step_partial_comp: JobID=%u range=%u-%u", - req->job_id, req->range_first, req->range_last); + error("step_partial_comp: StepID=%u.%u range=%u-%u", + req->job_id, req->job_step_id, req->range_first, + req->range_last); return EINVAL; } @@ -2268,8 +2286,10 @@ extern int step_partial_comp(step_complete_msg_t *req, uid_t uid, /* initialize the node bitmap for exited nodes */ nodes = bit_set_count(step_ptr->step_node_bitmap); if (req->range_last >= nodes) { /* range is zero origin */ - error("step_partial_comp: JobID=%u last=%u, nodes=%d", - req->job_id, req->range_last, nodes); + error("step_partial_comp: StepID=%u.%u last=%u " + "nodes=%d", + req->job_id, req->job_step_id, req->range_last, + nodes); return EINVAL; } step_ptr->exit_node_bitmap = bit_alloc(nodes); @@ -2279,8 +2299,10 @@ extern int step_partial_comp(step_complete_msg_t *req, uid_t uid, } else { nodes = _bitstr_bits(step_ptr->exit_node_bitmap); if (req->range_last >= nodes) { /* range is zero origin */ - error("step_partial_comp: JobID=%u last=%u, nodes=%d", - req->job_id, req->range_last, nodes); + error("step_partial_comp: StepID=%u.%u last=%u " + "nodes=%d", + req->job_id, req->job_step_id, req->range_last, + nodes); return EINVAL; } step_ptr->exit_code = MAX(step_ptr->exit_code, req->step_rc); diff --git a/src/slurmd/slurmd/req.c b/src/slurmd/slurmd/req.c index c6d71e2c3..e86d0d22f 100644 --- a/src/slurmd/slurmd/req.c +++ b/src/slurmd/slurmd/req.c @@ -836,14 +836,6 @@ _check_job_credential(launch_tasks_request_msg_t *req, uid_t uid, error("cons_res: zero processors allocated to step"); step_cores = 1; } - if (tasks_to_launch > step_cores) { - /* This is expected with the --overcommit option - * or hyperthreads */ - debug("cons_res: More than one tasks per logical " - "processor (%d > %u) on host [%u.%u %ld %s] ", - tasks_to_launch, step_cores, arg.jobid, - arg.stepid, (long) arg.uid, arg.step_hostlist); - } /* NOTE: step_cores is the count of allocated resources * (typically cores). Convert to CPU count as needed */ if (i_last_bit <= i_first_bit) @@ -855,6 +847,14 @@ _check_job_credential(launch_tasks_request_msg_t *req, uid_t uid, step_cores *= i; } } + if (tasks_to_launch > step_cores) { + /* This is expected with the --overcommit option + * or hyperthreads */ + debug("cons_res: More than one tasks per logical " + "processor (%d > %u) on host [%u.%u %ld %s] ", + tasks_to_launch, step_cores, arg.jobid, + arg.stepid, (long) arg.uid, arg.step_hostlist); + } } else { step_cores = 1; job_cores = 1; @@ -1042,18 +1042,28 @@ _rpc_launch_tasks(slurm_msg_t *msg) static void _prolog_error(batch_job_launch_msg_t *req, int rc) { - char *err_name_ptr, err_name[128], path_name[MAXPATHLEN]; + char *err_name_ptr, err_name[256], path_name[MAXPATHLEN]; + char *fmt_char; int fd; - if (req->std_err) - err_name_ptr = req->std_err; - else if (req->std_out) - err_name_ptr = req->std_out; - else { + if (req->std_err || req->std_out) { + if (req->std_err) + strncpy(err_name, req->std_err, sizeof(err_name)); + else + strncpy(err_name, req->std_out, sizeof(err_name)); + if ((fmt_char = strchr(err_name, (int) '%')) && + (fmt_char[1] == 'j') && !strchr(fmt_char+1, (int) '%')) { + char tmp_name[256]; + fmt_char[1] = 'u'; + snprintf(tmp_name, sizeof(tmp_name), err_name, + req->job_id); + strncpy(err_name, tmp_name, sizeof(err_name)); + } + } else { snprintf(err_name, sizeof(err_name), "slurm-%u.out", req->job_id); - err_name_ptr = err_name; } + err_name_ptr = err_name; if (err_name_ptr[0] == '/') snprintf(path_name, MAXPATHLEN, "%s", err_name_ptr); else if (req->work_dir) @@ -3660,6 +3670,10 @@ _build_env(uint32_t jobid, uid_t uid, char *resv_id, if (resv_id) { #ifdef HAVE_BG setenvf(&env, "MPIRUN_PARTITION", "%s", resv_id); +# ifdef HAVE_BGP + /* Needed for HTC jobs */ + setenvf(&env, "SUBMIT_POOL", "%s", resv_id); +# endif #endif #ifdef HAVE_CRAY setenvf(&env, "BASIL_RESERVATION_ID", "%s", resv_id); diff --git a/src/slurmd/slurmd/slurmd.c b/src/slurmd/slurmd/slurmd.c index b499bbe5d..f1e8a3b11 100644 --- a/src/slurmd/slurmd/slurmd.c +++ b/src/slurmd/slurmd/slurmd.c @@ -1,6 +1,6 @@ /*****************************************************************************\ * src/slurmd/slurmd/slurmd.c - main slurm node server daemon - * $Id: slurmd.c 21936 2010-12-29 22:11:02Z jette $ + * $Id: slurmd.c 22502 2011-02-16 22:30:25Z jette $ ***************************************************************************** * Copyright (C) 2002-2007 The Regents of the University of California. * Copyright (C) 2008-2010 Lawrence Livermore National Security. @@ -776,7 +776,8 @@ _read_config(void) &conf->block_map, &conf->block_map_inv); if (((cf->fast_schedule == 0) && !cr_flag && !gang_flag) || - (conf->actual_cpus < conf->conf_cpus)) { + ((cf->fast_schedule == 1) && + (conf->actual_cpus < conf->conf_cpus))) { conf->cpus = conf->actual_cpus; conf->sockets = conf->actual_sockets; conf->cores = conf->actual_cores; diff --git a/src/smap/partition_functions.c b/src/smap/partition_functions.c index 904059642..6ee360735 100644 --- a/src/smap/partition_functions.c +++ b/src/smap/partition_functions.c @@ -419,14 +419,18 @@ static int _marknodes(db2_block_info_t *block_ptr, int count) && (block_ptr->nodes[j+4] == 'x' || block_ptr->nodes[j+4] == '-')) { j++; - number = strtoul(block_ptr->nodes + j, &p, - params.cluster_base); + + number = xstrntol(block_ptr->nodes + j, &p, + params.cluster_dims, + params.cluster_base); + hostlist_parse_int_to_array( number, start, params.cluster_dims, params.cluster_base); j += 4; - number = strtoul(block_ptr->nodes + j, &p, - params.cluster_base); + number = xstrntol(block_ptr->nodes + j, &p, + params.cluster_dims, + params.cluster_base); hostlist_parse_int_to_array( number, end, params.cluster_dims, params.cluster_base); @@ -446,8 +450,9 @@ static int _marknodes(db2_block_info_t *block_ptr, int count) || (block_ptr->nodes[j] >= 'A' && block_ptr->nodes[j] <= 'Z')) { - number = strtoul(block_ptr->nodes + j, &p, - params.cluster_base); + number = xstrntol(block_ptr->nodes + j, &p, + params.cluster_dims, + params.cluster_base); hostlist_parse_int_to_array( number, start, params.cluster_dims, params.cluster_base); @@ -564,13 +569,10 @@ static int _print_text_part(partition_info_t *part_ptr, snprintf(tmp_cnt, sizeof(tmp_cnt), "%u", part_ptr->total_nodes); if(!params.commandline) { - uint16_t root_only = 0; - if (part_ptr->flags & PART_FLAG_ROOT_ONLY) - root_only = 1; mvwprintw(text_win, main_ycord, main_xcord, "%c", - root_only); + part_ptr->flags); main_xcord += 4; if (part_ptr->name) { diff --git a/src/squeue/opts.c b/src/squeue/opts.c index cdd3d43eb..b2ce88bcc 100644 --- a/src/squeue/opts.c +++ b/src/squeue/opts.c @@ -60,6 +60,7 @@ #include "src/common/read_config.h" #include "src/common/xstring.h" #include "src/common/proc_args.h" +#include "src/common/uid.h" #include "src/squeue/squeue.h" @@ -79,7 +80,7 @@ static List _build_user_list( char* str ); static char *_get_prefix(char *token); static void _help( void ); static int _max_cpus_per_node(void); -static int _parse_state( char* str, enum job_states* states ); +static int _parse_state( char* str, uint16_t* states ); static void _parse_token( char *token, char *field, int *field_size, bool *right_justify, char **suffix); static void _print_options( void ); @@ -394,13 +395,13 @@ static int _max_cpus_per_node(void) * RET 0 or error code */ static int -_parse_state( char* str, enum job_states* states ) +_parse_state( char* str, uint16_t* states ) { int i; char *state_names; if ((i = job_state_num(str)) >= 0) { - *states = i; + *states = (uint16_t) i; return SLURM_SUCCESS; } @@ -961,7 +962,7 @@ _build_state_list( char* str ) { List my_list; char *state = NULL, *tmp_char = NULL, *my_state_list = NULL; - enum job_states *state_id = NULL; + uint16_t *state_id = NULL; if ( str == NULL) return NULL; @@ -975,9 +976,7 @@ _build_state_list( char* str ) { state_id = xmalloc( sizeof( uint16_t ) ); if ( _parse_state( state, state_id ) != SLURM_SUCCESS ) - { exit( 1 ); - } list_append( my_list, state_id ); state = strtok_r( NULL, ",", &tmp_char ); } @@ -1066,29 +1065,22 @@ _build_user_list( char* str ) { List my_list; char *user = NULL; - char *tmp_char = NULL, *my_user_list = NULL, *end_ptr = NULL; - uint32_t *uid = NULL; - struct passwd *passwd_ptr = NULL; + char *tmp_char = NULL, *my_user_list = NULL; - if ( str == NULL) + if ( str == NULL ) return NULL; my_list = list_create( NULL ); my_user_list = xstrdup( str ); user = strtok_r( my_user_list, ",", &tmp_char ); while (user) { - uid = xmalloc( sizeof( uint32_t )); - *uid = (uint32_t) strtol(user, &end_ptr, 10); - if (end_ptr[0] == '\0') - list_append( my_list, uid ); - else { - passwd_ptr = getpwnam( user ); - if (passwd_ptr == NULL) { - error( "Invalid user: %s\n", user); - xfree(uid); - } else { - *uid = passwd_ptr->pw_uid; - list_append( my_list, uid ); - } + uid_t some_uid; + if ( uid_from_string( user, &some_uid ) == 0 ) { + uint32_t *user_id = NULL; + user_id = xmalloc( sizeof( uint32_t )); + *user_id = (uint32_t) some_uid; + list_append( my_list, user_id ); + } else { + error( "Invalid user: %s\n", user); } user = strtok_r (NULL, ",", &tmp_char); } diff --git a/src/squeue/print.c b/src/squeue/print.c index 489248570..c74723b24 100644 --- a/src/squeue/print.c +++ b/src/squeue/print.c @@ -732,12 +732,21 @@ int _print_job_num_sct(job_info_t * job, int width, bool right_justify, char threads[10]; char sct[(10+1)*3]; if (job) { - convert_num_unit((float)job->sockets_per_node, sockets, - sizeof(sockets), UNIT_NONE); - convert_num_unit((float)job->cores_per_socket, cores, - sizeof(cores), UNIT_NONE); - convert_num_unit((float)job->threads_per_core, threads, - sizeof(threads), UNIT_NONE); + if (job->sockets_per_node == (uint16_t) NO_VAL) + strcpy(sockets, "*"); + else + convert_num_unit((float)job->sockets_per_node, sockets, + sizeof(sockets), UNIT_NONE); + if (job->cores_per_socket == (uint16_t) NO_VAL) + strcpy(cores, "*"); + else + convert_num_unit((float)job->cores_per_socket, cores, + sizeof(cores), UNIT_NONE); + if (job->threads_per_core == (uint16_t) NO_VAL) + strcpy(threads, "*"); + else + convert_num_unit((float)job->threads_per_core, threads, + sizeof(threads), UNIT_NONE); sct[0] = '\0'; strcat(sct, sockets); strcat(sct, ":"); @@ -826,7 +835,10 @@ int _print_sockets(job_info_t * job, int width, bool right_justify, if (job == NULL) /* Print the Header instead */ _print_str("SOCKETS_PER_NODE", width, right_justify, true); else { - convert_num_unit((float)job->sockets_per_node, tmp_char, + if (job->sockets_per_node == (uint16_t) NO_VAL) + strcpy(tmp_char, "*"); + else + convert_num_unit((float)job->sockets_per_node, tmp_char, sizeof(tmp_char), UNIT_NONE); _print_str(tmp_char, width, right_justify, true); } @@ -843,8 +855,11 @@ int _print_cores(job_info_t * job, int width, bool right_justify, if (job == NULL) /* Print the Header instead */ _print_str("CORES_PER_SOCKET", width, right_justify, true); else { - convert_num_unit((float)job->cores_per_socket, tmp_char, - sizeof(tmp_char), UNIT_NONE); + if (job->cores_per_socket == (uint16_t) NO_VAL) + strcpy(tmp_char, "*"); + else + convert_num_unit((float)job->cores_per_socket, tmp_char, + sizeof(tmp_char), UNIT_NONE); _print_str(tmp_char, width, right_justify, true); } if (suffix) @@ -860,8 +875,11 @@ int _print_threads(job_info_t * job, int width, bool right_justify, if (job == NULL) /* Print the Header instead */ _print_str("THREADS_PER_CORE", width, right_justify, true); else { - convert_num_unit((float)job->threads_per_core, tmp_char, - sizeof(tmp_char), UNIT_NONE); + if (job->threads_per_core == (uint16_t) NO_VAL) + strcpy(tmp_char, "*"); + else + convert_num_unit((float)job->threads_per_core, tmp_char, + sizeof(tmp_char), UNIT_NONE); _print_str(tmp_char, width, right_justify, true); } if (suffix) @@ -1291,7 +1309,7 @@ static int _filter_job(job_info_t * job) int filter; ListIterator iterator; uint32_t *job_id, *user; - enum job_states *state_id; + uint16_t *state_id; char *account, *part, *qos; if (params.job_list) { @@ -1337,7 +1355,7 @@ static int _filter_job(job_info_t * job) iterator = list_iterator_create(params.account_list); while ((account = list_next(iterator))) { if ((job->account != NULL) && - (strcmp(account, job->account) == 0)) { + (strcasecmp(account, job->account) == 0)) { filter = 0; break; } @@ -1352,7 +1370,7 @@ static int _filter_job(job_info_t * job) iterator = list_iterator_create(params.qos_list); while ((qos = list_next(iterator))) { if ((job->qos != NULL) && - (strcmp(qos, job->qos) == 0)) { + (strcasecmp(qos, job->qos) == 0)) { filter = 0; break; } diff --git a/src/sreport/job_reports.c b/src/sreport/job_reports.c index 531e3adcd..64e2cf1f4 100644 --- a/src/sreport/job_reports.c +++ b/src/sreport/job_reports.c @@ -38,6 +38,7 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. \*****************************************************************************/ +#include "src/common/uid.h" #include "job_reports.h" enum { @@ -133,6 +134,19 @@ static int _sort_acct_grouping_dec(slurmdb_report_acct_grouping_t *acct_a, return 0; } + +static char *_string_to_uid( char *name ) +{ + uid_t uid; + if ( uid_from_string( name, &uid ) != 0 ) { + fprintf(stderr, "Invalid user id: %s\n", name); + exit(1); + } + xfree(name); + return xstrdup_printf( "%d", (int) uid ); +} + + /* returns number of objects added to list */ static int _addto_uid_char_list(List char_list, char *names) { @@ -167,19 +181,7 @@ static int _addto_uid_char_list(List char_list, char *names) name = xmalloc((i-start+1)); memcpy(name, names+start, (i-start)); //info("got %s %d", name, i-start); - if (!isdigit((int) *name)) { - struct passwd *pwd; - if (!(pwd=getpwnam(name))) { - fprintf(stderr, - "Invalid user " - "id: %s\n", - name); - exit(1); - } - xfree(name); - name = xstrdup_printf( - "%d", pwd->pw_uid); - } + name = _string_to_uid( name ); while((tmp_char = list_next(itr))) { if(!strcasecmp(tmp_char, name)) @@ -207,18 +209,7 @@ static int _addto_uid_char_list(List char_list, char *names) if((i-start) > 0) { name = xmalloc((i-start)+1); memcpy(name, names+start, (i-start)); - - if (!isdigit((int) *name)) { - struct passwd *pwd; - if (!(pwd=getpwnam(name))) { - fprintf(stderr, - "Invalid user id: %s\n", - name); - exit(1); - } - xfree(name); - name = xstrdup_printf("%d", pwd->pw_uid); - } + name = _string_to_uid( name ); while((tmp_char = list_next(itr))) { if(!strcasecmp(tmp_char, name)) diff --git a/src/strigger/opts.c b/src/strigger/opts.c index 77ec8fdf3..4a4e94637 100644 --- a/src/strigger/opts.c +++ b/src/strigger/opts.c @@ -61,6 +61,7 @@ #include "src/common/xmalloc.h" #include "src/common/xstring.h" #include "src/common/proc_args.h" +#include "src/common/uid.h" #include "src/strigger/strigger.h" @@ -91,6 +92,7 @@ extern void parse_command_line(int argc, char *argv[]) int first = 1; int opt_char; int option_index; + uid_t some_uid; long tmp_l; static struct option long_options[] = { {"primary_slurmctld_failure", no_argument, 0, 'a'}, @@ -268,17 +270,11 @@ extern void parse_command_line(int argc, char *argv[]) params.mode_set = true; break; case (int) OPT_LONG_USER: - if ((optarg[0] >= '0') && (optarg[0] <= '9')) - params.user_id = (uint32_t) atol(optarg); - else { - struct passwd *pw; - pw = getpwnam(optarg); - if (pw == NULL) { - error("Invalid user %s", optarg); - exit(1); - } - params.user_id = pw->pw_uid; + if ( uid_from_string( optarg, &some_uid ) != 0 ) { + error("Invalid user %s", optarg); + exit(1); } + params.user_id = (uint32_t) some_uid; break; } } diff --git a/src/sview/block_info.c b/src/sview/block_info.c index d759ec5a4..8db14a741 100644 --- a/src/sview/block_info.c +++ b/src/sview/block_info.c @@ -532,8 +532,17 @@ static List _create_block_list(partition_info_msg_t *part_info_ptr, block_ptr->color_inx = atoi(block_ptr->bg_block_name+7); #else - block_ptr->color_inx = - atoi(block_ptr->bg_block_name+3); + /* If on a non-bluegene system and looking at one + check for strlen, if it is more than 7 go with + that, or you could get everone being the same + color. + */ + if (strlen(block_ptr->bg_block_name) >= 7) + block_ptr->color_inx = + atoi(block_ptr->bg_block_name+7); + else + block_ptr->color_inx = + atoi(block_ptr->bg_block_name+3); #endif /* on some systems they make there own blocks named whatever they want, so doing this fixes what could diff --git a/src/sview/grid.c b/src/sview/grid.c index c730bdb8b..81dca9e86 100644 --- a/src/sview/grid.c +++ b/src/sview/grid.c @@ -81,7 +81,7 @@ static int _coord(char coord) if ((coord >= '0') && (coord <= '9')) return (coord - '0'); if ((coord >= 'A') && (coord <= 'Z')) - return (coord - 'A'); + return ((coord - 'A') + 10); return -1; } diff --git a/src/sview/node_info.c b/src/sview/node_info.c index 7de54e74c..0ae9209db 100644 --- a/src/sview/node_info.c +++ b/src/sview/node_info.c @@ -629,6 +629,7 @@ extern List create_node_info_list(node_info_msg_t *node_info_ptr, for (i=0; i<node_info_ptr->record_count; i++) { node_ptr = &(node_info_ptr->node_array[i]); + if (!node_ptr->name || (node_ptr->name[0] == '\0')) continue; diff --git a/src/sview/part_info.c b/src/sview/part_info.c index 6206b1ecd..0f7b5770c 100644 --- a/src/sview/part_info.c +++ b/src/sview/part_info.c @@ -1575,6 +1575,7 @@ static List _create_part_info_list(partition_info_msg_t *part_info_ptr, for (i=0; i<part_info_ptr->record_count; i++) { part_ptr = &(part_info_ptr->partition_array[i]); + /* don't include configured excludes */ if (!working_sview_config.show_hidden && part_ptr->flags & PART_FLAG_HIDDEN) diff --git a/src/sview/resv_info.c b/src/sview/resv_info.c index e6035ea26..3187bacba 100644 --- a/src/sview/resv_info.c +++ b/src/sview/resv_info.c @@ -53,6 +53,7 @@ enum { SORTID_DURATION, SORTID_FEATURES, SORTID_FLAGS, + SORTID_LICENSES, SORTID_NAME, SORTID_NODE_CNT, SORTID_NODELIST, @@ -102,6 +103,8 @@ static display_data_t display_data_resv[] = { refresh_resv, create_model_resv, admin_edit_resv}, {G_TYPE_STRING, SORTID_ACCOUNTS, "Accounts", FALSE, EDIT_TEXTBOX, refresh_resv, create_model_resv, admin_edit_resv}, + {G_TYPE_STRING, SORTID_LICENSES, "Licenses", TRUE, EDIT_TEXTBOX, + refresh_resv, create_model_resv, admin_edit_resv}, {G_TYPE_STRING, SORTID_USERS, "Users", FALSE, EDIT_TEXTBOX, refresh_resv, create_model_resv, admin_edit_resv}, {G_TYPE_STRING, SORTID_PARTITION, "Partition", FALSE, EDIT_TEXTBOX, @@ -291,6 +294,10 @@ static const char *_set_resv_msg(resv_desc_msg_t *resv_msg, goto return_error; resv_msg->flags = f; break; + case SORTID_LICENSES: + resv_msg->licenses = xstrdup(new_text); + type = "licenses"; + break; case SORTID_NAME: resv_msg->name = xstrdup(new_text); type = "name"; @@ -479,6 +486,11 @@ static void _layout_resv_record(GtkTreeView *treeview, temp_char); xfree(temp_char); + add_display_treestore_line(update, treestore, &iter, + find_col_name(display_data_resv, + SORTID_LICENSES), + resv_ptr->licenses); + convert_num_unit((float)resv_ptr->node_cnt, time_buf, sizeof(time_buf), UNIT_NONE); add_display_treestore_line(update, treestore, &iter, @@ -549,6 +561,9 @@ static void _update_resv_record(sview_resv_info_t *sview_resv_info_ptr, tmp_ptr, -1); xfree(tmp_ptr); + gtk_tree_store_set(treestore, iter, + SORTID_LICENSES, resv_ptr->licenses, -1); + gtk_tree_store_set(treestore, iter, SORTID_NAME, resv_ptr->name, -1); convert_num_unit((float)resv_ptr->node_cnt, @@ -697,6 +712,7 @@ static List _create_resv_info_list(reserve_info_msg_t *resv_info_ptr, for(i=0; i<resv_info_ptr->record_count; i++) { resv_ptr = &(resv_info_ptr->reservation_array[i]); + sview_resv_info_ptr = xmalloc(sizeof(sview_resv_info_t)); sview_resv_info_ptr->resv_ptr = resv_ptr; sview_resv_info_ptr->color_inx = i % sview_colors_cnt; diff --git a/src/sview/sview.c b/src/sview/sview.c index 29f7fabcc..dbe5d5927 100644 --- a/src/sview/sview.c +++ b/src/sview/sview.c @@ -709,7 +709,7 @@ static GtkWidget *_get_menubar_menu(GtkWidget *window, GtkWidget *notebook) {"exit", GTK_STOCK_QUIT, "E_xit", "<control>x", "Exits Program", G_CALLBACK(_delete)}, {"help", NULL, "_Help", "<alt>h"}, - {"about", GTK_STOCK_ABOUT, "A_bout", "<control>b", + {"about", GTK_STOCK_ABOUT, "Ab_out", "<control>o", "About", G_CALLBACK(about_popup)}, //{"manual", GTK_STOCK_HELP, "_Manual", "<control>m"}, {"grid_specs", GTK_STOCK_EDIT, "Set Grid _Properties", diff --git a/testsuite/expect/test1.26 b/testsuite/expect/test1.26 index 32a5b7adf..e2bb45228 100755 --- a/testsuite/expect/test1.26 +++ b/testsuite/expect/test1.26 @@ -36,7 +36,7 @@ source ./globals set test_id "1.26" -set interations 100 +set iterations 100 set exit_code 0 print_header $test_id @@ -156,7 +156,7 @@ if {[string compare $host_1 $include_node]} { set front_end [test_front_end] set successes 0 -for {set inx 0} {$inx < $interations} {incr inx} { +for {set inx 0} {$inx < $iterations} {incr inx} { exec $bin_usleep 250000 set failures 0 @@ -256,8 +256,8 @@ for {set inx 0} {$inx < $interations} {incr inx} { set exit_code 1 } } -if {$successes != $interations} { - send_user "\nFAILURE: only $successes of $interations completed successfully\n" +if {$successes != $iterations} { + send_user "\nFAILURE: only $successes of $iterations completed successfully\n" } if {$exit_code == 0} { diff --git a/testsuite/expect/test1.84 b/testsuite/expect/test1.84 index 0ee2dbef3..614cbce91 100755 --- a/testsuite/expect/test1.84 +++ b/testsuite/expect/test1.84 @@ -63,7 +63,7 @@ set host "" set timeout $max_job_delay set task_cnt 0 -set srun_pid [spawn $srun -N1 --cpus-per-task=1 --threads-per-core=1 --exclusive -l -t1 $file_in] +set srun_pid [spawn $srun -N1 --cpus-per-task=1 --exclusive -l -t1 $file_in] expect { -re "SLURM_CPUS_ON_NODE=($number) SLURMD_NODENAME=($alpha_numeric_under)" { set cpu_cnt $expect_out(1,string) @@ -99,6 +99,7 @@ if {[string compare $host ""] == 0} { } # Convert CPU count to core count if necessary if {$cpu_cnt != $task_cnt} { + set core_cnt $cpu_cnt set threads_per_core 1 spawn $scontrol show node $host expect { @@ -115,10 +116,10 @@ if {$cpu_cnt != $task_cnt} { } } if {$threads_per_core != 0} { - set cpu_cnt [expr $cpu_cnt / $threads_per_core] + set cpu_cnt [expr $cpu_cnt * $threads_per_core] } if {$cpu_cnt == $task_cnt} { - send_user "NOTE: Allocated cores and $threads_per_core CPUs per core\n" + send_user "NOTE: Allocated $core_cnt cores and $threads_per_core CPUs per core\n" } } if {$cpu_cnt != $task_cnt} { @@ -133,10 +134,10 @@ if {$cpu_cnt < 2} { } # -# Submit a 1 node job to determine the node's CPU count +# Now verify the --cpus-per-task option # set task_cnt 0 -set srun_pid [spawn $srun -N1 -t1 --nodelist=$host --cpus-per-task=2 --threads-per-core=1 --exclusive -l $bin_printenv SLURMD_NODENAME] +set srun_pid [spawn $srun -N1 --cpus-per-task=2 --exclusive -l -t1 --nodelist=$host $bin_printenv SLURMD_NODENAME] expect { -re "Invalid node name specified" { send_user "\nWARNING: Appears you are using " @@ -159,7 +160,7 @@ expect { } # -# Check CPU count +# Verify that half the number of tasks were spawned # if {$task_cnt != [expr $cpu_cnt / 2]} { send_user "\nFAILURE: Improper task count for given cpus-per-task\n" diff --git a/testsuite/expect/test6.13 b/testsuite/expect/test6.13 index 30ef63153..eb7ceb41d 100755 --- a/testsuite/expect/test6.13 +++ b/testsuite/expect/test6.13 @@ -159,6 +159,7 @@ make_bash_script $file_in " echo BEGIN $bin_sleep 10 $bin_sleep 10 + $bin_sleep 10 echo FINI " diff --git a/testsuite/expect/test7.2.prog.c b/testsuite/expect/test7.2.prog.c index bc54443fc..e77f71958 100644 --- a/testsuite/expect/test7.2.prog.c +++ b/testsuite/expect/test7.2.prog.c @@ -359,7 +359,7 @@ main (int argc, char **argv) /* Replicate the very heavy load that MVAPICH2 puts on PMI * This load exceeds that of MPICH2 by a very wide margin */ #if _DEBUG - printf("Starting %d interations each with %d PMI_KVS_Put and \n" + printf("Starting %d iterations each with %d PMI_KVS_Put and \n" " one each PMI_KVS_Commit and KVS_Barrier\n", BARRIER_CNT, PUTS_PER_BARRIER); fflush(stdout); diff --git a/testsuite/expect/test9.7 b/testsuite/expect/test9.7 index ef8cb7fcb..190500291 100755 --- a/testsuite/expect/test9.7 +++ b/testsuite/expect/test9.7 @@ -35,7 +35,7 @@ source ./globals set test_id "9.7" set exit_code 0 set file_script "./test$test_id.bash" -set interations 5 +set iterations 5 set sleep_time 1 set task_cnt 10 @@ -53,7 +53,7 @@ if {[test_front_end] != 0} { # Initiate $task_cnt parallel tasks # for {set inx 0} {$inx < $task_cnt} {incr inx} { - spawn $bin_bash $file_script $sinfo $srun $squeue $sleep_time $interations [test_bluegene] + spawn $bin_bash $file_script $sinfo $srun $squeue $sleep_time $iterations [test_bluegene] set task_id($inx) $spawn_id } @@ -61,7 +61,7 @@ for {set inx 0} {$inx < $task_cnt} {incr inx} { # Test output for successful completion messasge # set success_cnt 0 -set timeout [expr $max_job_delay * $interations * $task_cnt] +set timeout [expr $max_job_delay * $iterations * $task_cnt] for {set inx 0} {$inx < $task_cnt} {incr inx} { set spawn_id $task_id($inx) expect { -- GitLab