diff --git a/doc/man/man1/srun.1 b/doc/man/man1/srun.1 index 1d592eee40736da65660faf6f4b7f48e73bc1b27..b78b7d96744dc23a79a274bffc45cc9a7fb0a9a9 100644 --- a/doc/man/man1/srun.1 +++ b/doc/man/man1/srun.1 @@ -131,6 +131,13 @@ If not specified, the scontrol show job will display 'ReqS:C:T=*:*:*'. .TP \fB\-\-bb\fR=<\fIspec\fR> Burst buffer specification. The form of the specification is system dependent. +Also see \fB\-\-bbf\fR. + +.TP +\fB\-\-bbf\fR=<\fIfile_name\fR> +Path of file containing burst buffer specification. +The form of the specification is system dependent. +Also see \fB\-\-bb\fR. .TP \fB\-\-begin\fR=<\fItime\fR> diff --git a/src/salloc/opt.c b/src/salloc/opt.c index 1ee01e6ebf0e4277c6f59cb45e25274bc4b455d1..5cce18f665bda496da3a18eb7a6d501e3b564e28 100644 --- a/src/salloc/opt.c +++ b/src/salloc/opt.c @@ -157,7 +157,8 @@ #define LONG_OPT_GET_USER_ENV 0x125 #define LONG_OPT_NETWORK 0x126 #define LONG_OPT_QOS 0x127 -#define LONG_OPT_BURST_BUFFER 0x128 +#define LONG_OPT_BURST_BUFFER_SPEC 0x128 +#define LONG_OPT_BURST_BUFFER_FILE 0x129 #define LONG_OPT_SOCKETSPERNODE 0x130 #define LONG_OPT_CORESPERSOCKET 0x131 #define LONG_OPT_THREADSPERCORE 0x132 @@ -206,9 +207,10 @@ static void _opt_list(void); /* verify options sanity */ static bool _opt_verify(void); - +static char *_read_file(char *fname); static void _proc_get_user_env(char *optarg); static void _process_env_var(env_vars_t *e, const char *val); + static void _usage(void); /*---[ end forward declarations of static functions ]---------------------*/ @@ -675,7 +677,8 @@ void set_options(const int argc, char **argv) {"exclude", required_argument, 0, 'x'}, {"acctg-freq", required_argument, 0, LONG_OPT_ACCTG_FREQ}, {"begin", required_argument, 0, LONG_OPT_BEGIN}, - {"bb", required_argument, 0, LONG_OPT_BURST_BUFFER}, + {"bb", required_argument, 0, LONG_OPT_BURST_BUFFER_SPEC}, + {"bbf", required_argument, 0, LONG_OPT_BURST_BUFFER_FILE}, {"bell", no_argument, 0, LONG_OPT_BELL}, {"blrts-image", required_argument, 0, LONG_OPT_BLRTS_IMAGE}, {"cnload-image", required_argument, 0, LONG_OPT_LINUX_IMAGE}, @@ -1245,10 +1248,14 @@ void set_options(const int argc, char **argv) } opt.req_switch = parse_int("switches", optarg, true); break; - case LONG_OPT_BURST_BUFFER: + case LONG_OPT_BURST_BUFFER_SPEC: xfree(opt.burst_buffer); opt.burst_buffer = xstrdup(optarg); break; + case LONG_OPT_BURST_BUFFER_FILE: + xfree(opt.burst_buffer); + opt.burst_buffer = _read_file(optarg); + break; case LONG_OPT_THREAD_SPEC: opt.core_spec = parse_int("thread_spec", optarg, true) | CORE_SPEC_THREAD; @@ -1743,6 +1750,40 @@ extern int spank_unset_job_env(const char *name) return 0; /* not found */ } +/* Read specified file's contents into a buffer. + * Caller must xfree the buffer's contents */ +static char *_read_file(char *fname) +{ + int fd, i, offset = 0; + struct stat stat_buf; + char *file_buf; + + fd = open(fname, O_RDONLY); + if (fd < 0) { + fatal("Could not open burst buffer specification file %s: %m", + fname); + } + if (fstat(fd, &stat_buf) < 0) { + fatal("Could not stat burst buffer specification file %s: %m", + fname); + } + file_buf = xmalloc(stat_buf.st_size); + while (stat_buf.st_size > offset) { + i = read(fd, file_buf + offset, stat_buf.st_size - offset); + if (i < 0) { + if (errno == EAGAIN) + continue; + fatal("Could not read burst buffer specification " + "file %s: %m", fname); + } + if (i == 0) + break; /* EOF */ + offset += i; + } + close(fd); + return file_buf; +} + /* helper function for printing options * * warning: returns pointer to memory allocated on the stack. @@ -1936,7 +1977,8 @@ static void _usage(void) " [--cpu-freq=min[-max[:gov]] [--sicp] [--power=flags]\n" " [--switches=max-switches[@max-time-to-wait]]\n" " [--core-spec=cores] [--thread-spec=threads] [--reboot]\n" -" [--bb=burst_buffer_spec] [executable [args...]]\n"); +" [--bb=burst_buffer_spec] [--bbf=burst_buffer_file]\n" +" [executable [args...]]\n"); } static void _help(void) @@ -1951,6 +1993,7 @@ static void _help(void) " --begin=time defer job until HH:MM MM/DD/YY\n" " --bell ring the terminal bell when the job is allocated\n" " --bb=<spec> burst buffer specifications\n" +" --bbf=<file_name> burst buffer specification file\n" " -c, --cpus-per-task=ncpus number of cpus required per task\n" " --comment=name arbitrary comment\n" " --cpu-freq=min[-max[:gov]] requested cpu frequency (and governor)\n" diff --git a/src/srun/libsrun/opt.c b/src/srun/libsrun/opt.c index 5835b844f15e841c0c898d94bc342f331df5346a..5beb47390874c97da10d94ac4ba7b4b457f935c1 100644 --- a/src/srun/libsrun/opt.c +++ b/src/srun/libsrun/opt.c @@ -68,9 +68,10 @@ #include <stdio.h> #include <stdlib.h> /* getenv */ #include <sys/param.h> /* MAXPATHLEN */ -#include <unistd.h> +#include <sys/stat.h> #include <sys/types.h> #include <sys/utsname.h> +#include <unistd.h> #include "src/common/cpu_frequency.h" #include "src/common/list.h" @@ -167,7 +168,8 @@ #define LONG_OPT_MULTI 0x122 #define LONG_OPT_COMMENT 0x124 #define LONG_OPT_QOS 0x127 -#define LONG_OPT_BURST_BUFFER 0x128 +#define LONG_OPT_BURST_BUFFER_SPEC 0x128 +#define LONG_OPT_BURST_BUFFER_FILE 0x129 #define LONG_OPT_SOCKETSPERNODE 0x130 #define LONG_OPT_CORESPERSOCKET 0x131 #define LONG_OPT_THREADSPERCORE 0x132 @@ -243,7 +245,7 @@ static void _opt_list(void); static bool _opt_verify(void); static void _process_env_var(env_vars_t *e, const char *val); - +static char *_read_file(char *fname); static bool _under_parallel_debugger(void); static void _usage(void); static bool _valid_node_list(char **node_list_pptr); @@ -900,7 +902,8 @@ static void _set_options(const int argc, char **argv) {"no-allocate", no_argument, 0, 'Z'}, {"accel-bind", required_argument, 0, LONG_OPT_ACCEL_BIND}, {"acctg-freq", required_argument, 0, LONG_OPT_ACCTG_FREQ}, - {"bb", required_argument, 0, LONG_OPT_BURST_BUFFER}, + {"bb", required_argument, 0, LONG_OPT_BURST_BUFFER_SPEC}, + {"bbf", required_argument, 0, LONG_OPT_BURST_BUFFER_FILE}, {"begin", required_argument, 0, LONG_OPT_BEGIN}, {"blrts-image", required_argument, 0, LONG_OPT_BLRTS_IMAGE}, {"checkpoint", required_argument, 0, LONG_OPT_CHECKPOINT}, @@ -1423,10 +1426,14 @@ static void _set_options(const int argc, char **argv) xfree(opt.epilog); opt.epilog = xstrdup(optarg); break; - case LONG_OPT_BURST_BUFFER: + case LONG_OPT_BURST_BUFFER_SPEC: xfree(opt.burst_buffer); opt.burst_buffer = xstrdup(optarg); break; + case LONG_OPT_BURST_BUFFER_FILE: + xfree(opt.burst_buffer); + opt.burst_buffer = _read_file(optarg); + break; case LONG_OPT_BEGIN: opt.begin = parse_time(optarg, 0); if (errno == ESLURM_INVALID_TIME_VALUE) { @@ -2544,6 +2551,40 @@ static void _opt_list(void) } +/* Read specified file's contents into a buffer. + * Caller must xfree the buffer's contents */ +static char *_read_file(char *fname) +{ + int fd, i, offset = 0; + struct stat stat_buf; + char *file_buf; + + fd = open(fname, O_RDONLY); + if (fd < 0) { + fatal("Could not open burst buffer specification file %s: %m", + fname); + } + if (fstat(fd, &stat_buf) < 0) { + fatal("Could not stat burst buffer specification file %s: %m", + fname); + } + file_buf = xmalloc(stat_buf.st_size); + while (stat_buf.st_size > offset) { + i = read(fd, file_buf + offset, stat_buf.st_size - offset); + if (i < 0) { + if (errno == EAGAIN) + continue; + fatal("Could not read burst buffer specification " + "file %s: %m", fname); + } + if (i == 0) + break; /* EOF */ + offset += i; + } + close(fd); + return file_buf; +} + /* Determine if srun is under the control of a parallel debugger or not */ static bool _under_parallel_debugger (void) { @@ -2597,7 +2638,8 @@ static void _usage(void) " [--ctrl-comm-ifhn=addr] [--multi-prog]\n" " [--cpu-freq=min[-max[:gov]] [--sicp] [--power=flags]\n" " [--switches=max-switches{@max-time-to-wait}] [--reboot]\n" -" [--core-spec=cores] [--thread-spec=threads] [--bb=burst_buffer_spec]\n" +" [--core-spec=cores] [--thread-spec=threads]\n" +" [--bb=burst_buffer_spec] [--bbf=burst_buffer_file]\n" " [--acctg-freq=<datatype>=<interval>\n" " [-w hosts...] [-x hosts...] executable [args...]\n"); @@ -2617,6 +2659,7 @@ static void _help(void) " task=<interval> energy=<interval>\n" " network=<interval> filesystem=<interval>\n" " --bb=<spec> burst buffer specifications\n" +" --bbf=<file_name> burst buffer specification file\n" " --begin=time defer job until HH:MM MM/DD/YY\n" " -c, --cpus-per-task=ncpus number of cpus required per task\n" " --checkpoint=time job step checkpoint interval\n"