From 9d53a1a66b5b8e670ae27502b7ca39ff78aca51c Mon Sep 17 00:00:00 2001
From: phung4 <phung4@unknown>
Date: Wed, 15 Sep 2004 00:02:26 +0000
Subject: [PATCH] added mods to accomodate BGL related job info

---
 doc/man/man1/srun.1                           | 15 ++++
 slurm/slurm.h.in                              |  9 ++
 src/api/init_msg.c                            |  3 +
 src/common/slurm_protocol_pack.c              | 13 +++
 src/plugins/select/bluegene/bluegene.c        | 28 ++++---
 src/plugins/select/bluegene/partition_sys.c   |  6 +-
 src/plugins/select/bluegene/select_bluegene.c | 11 +--
 src/slurmctld/job_mgr.c                       | 31 +++++++
 src/slurmctld/proc_req.c                      |  2 +-
 src/slurmctld/slurmctld.h                     |  3 +
 src/srun/allocate.c                           | 59 +++++++++++++
 src/srun/opt.c                                | 84 ++++++++++++++++++-
 src/srun/opt.h                                |  3 +
 src/srun/srun.c                               |  1 -
 14 files changed, 239 insertions(+), 29 deletions(-)

diff --git a/doc/man/man1/srun.1 b/doc/man/man1/srun.1
index 053f4dbb376..60d7c57dbbf 100644
--- a/doc/man/man1/srun.1
+++ b/doc/man/man1/srun.1
@@ -343,6 +343,21 @@ Request that a specific list of hosts not be included in the resources
 allocated to this job. The host list will be assumed to be a filename 
 if it contains a "/"character.
 
+.PP
+BGL related options
+.TP
+\fB\-\-geometry\fR, \fB-g\fR
+Specify the geometry requirements for the job.
+.TP
+\fB\-\-conn-type\fR
+Require the partition connection type to be of a certain type.  The
+possible options are Mesh, Torus, or Nav.  If Nav, or if not set, then
+SLURM will try to fit a Torus else Mesh.
+.TP
+\fB\-\-rotate\fR, \fB-R\fR
+Specify whether SLURM is allowed to rotate the job request in order to
+fit an appropriate partition.
+
 .PP
 Help options
 .TP
diff --git a/slurm/slurm.h.in b/slurm/slurm.h.in
index 61d4263a294..170ae967d86 100644
--- a/slurm/slurm.h.in
+++ b/slurm/slurm.h.in
@@ -28,6 +28,12 @@
 #ifndef _SLURM_H
 #define _SLURM_H
 
+#define SYSTEM_DIMENSIONS 3
+#define X_DIMENSION 8
+#define Y_DIMENSION 4
+#define Z_DIMENSION 4
+enum connection_type {RM_MESH, RM_TORUS, RM_NAV};
+
 /* BEGIN_C_DECLS should be used at the beginning of your declarations,
    so that C++ compilers don't mangle their names.  Use _END_C_DECLS at
    the end of C declarations. */
@@ -252,6 +258,9 @@ typedef struct job_descriptor {	/* For submit, allocate, and update requests */
 	char *host;		/* host to contact initiating srun */
 	uint32_t dependency;	/* defer until specified job completes */
 	char *account;		/* charge to specified account */
+        uint16_t geometry[SYSTEM_DIMENSIONS];
+	uint16_t type;
+	uint16_t rotate;
 } job_desc_msg_t;
 
 typedef struct job_info {
diff --git a/src/api/init_msg.c b/src/api/init_msg.c
index 78d3597989c..d194d9a3be2 100644
--- a/src/api/init_msg.c
+++ b/src/api/init_msg.c
@@ -79,6 +79,9 @@ void slurm_init_job_desc_msg(job_desc_msg_t * job_desc_msg)
 	job_desc_msg->work_dir    = NULL;
 	job_desc_msg->host        = NULL;
 	job_desc_msg->port        = 0;
+	job_desc_msg->geometry[0] = NO_VAL;
+	job_desc_msg->type        = NO_VAL;
+	job_desc_msg->rotate      = NO_VAL;
 }
 
 /*
diff --git a/src/common/slurm_protocol_pack.c b/src/common/slurm_protocol_pack.c
index 29eab7c2f8f..dc4cd9f6ac5 100644
--- a/src/common/slurm_protocol_pack.c
+++ b/src/common/slurm_protocol_pack.c
@@ -1829,6 +1829,8 @@ _unpack_slurm_ctl_conf_msg(slurm_ctl_conf_info_msg_t **
 static void
 _pack_job_desc_msg(job_desc_msg_t * job_desc_ptr, Buf buffer)
 {
+	uint32_t i;
+
 	/* load the data values */
 	pack16(job_desc_ptr->contiguous, buffer);
 	pack16(job_desc_ptr->kill_on_node_fail, buffer);
@@ -1873,6 +1875,11 @@ _pack_job_desc_msg(job_desc_msg_t * job_desc_ptr, Buf buffer)
 
 	pack16(job_desc_ptr->port, buffer);
 	packstr(job_desc_ptr->host, buffer);
+
+	for (i=0; i<SYSTEM_DIMENSIONS; i++)
+		pack16(job_desc_ptr->geometry[i], buffer);		
+	pack16(job_desc_ptr->type, buffer);
+	pack16(job_desc_ptr->rotate, buffer);
 }
 
 /* _unpack_job_desc_msg
@@ -1886,6 +1893,7 @@ _unpack_job_desc_msg(job_desc_msg_t ** job_desc_buffer_ptr, Buf buffer)
 {
 	uint16_t uint16_tmp;
 	job_desc_msg_t *job_desc_ptr;
+	uint32_t i;
 
 	/* alloc memory for structure */
 	job_desc_ptr = xmalloc(sizeof(job_desc_msg_t));
@@ -1936,6 +1944,11 @@ _unpack_job_desc_msg(job_desc_msg_t ** job_desc_buffer_ptr, Buf buffer)
 	safe_unpack16(&job_desc_ptr->port, buffer);
 	safe_unpackstr_xmalloc(&job_desc_ptr->host, &uint16_tmp, buffer);
 
+	for(i=0; i<SYSTEM_DIMENSIONS; i++)
+		safe_unpack16(&(job_desc_ptr->geometry[i]), buffer);
+	safe_unpack16(&job_desc_ptr->type, buffer);
+	safe_unpack16(&job_desc_ptr->rotate, buffer);
+
 	return SLURM_SUCCESS;
 
       unpack_error:
diff --git a/src/plugins/select/bluegene/bluegene.c b/src/plugins/select/bluegene/bluegene.c
index cb77cfeb1f7..56cdfb1ac4a 100644
--- a/src/plugins/select/bluegene/bluegene.c
+++ b/src/plugins/select/bluegene/bluegene.c
@@ -217,7 +217,7 @@ static int _copy_slurm_partition_list()
 
 			bgl_record->nodes = strdup(cur_nodes);
 			bgl_record->slurm_part_id = slurm_part->name;
-			bgl_record->part_type = (rm_partition_t*) malloc(sizeof(rm_partition_t));
+			bgl_record->part_type = (rm_partition_t*) xmalloc(sizeof(rm_partition_t));
 			if (!bgl_record->part_type){
 				error("_copy_slurm_partition_list: not enough memory for bgl_record->part_type");
 				err = 1;
@@ -369,7 +369,7 @@ static int _parse_bgl_spec(char *in_line)
 	}
 
 	new_record->nodes = strdup(nodes);
-	new_record->part_type = malloc(sizeof(rm_partition_t));
+	new_record->part_type = xmalloc(sizeof(rm_partition_t));
 	if (strcasecmp(part_type, "TORUS") == 0){
 		// error("warning, TORUS specified, but I can't handle those yet!  Defaulting to mesh");
 		/** FIXME */
@@ -437,7 +437,7 @@ int _find_part_type(char* nodes, rm_partition_t** return_part_type)
 						      (ListFindF) _ListFindF_conf_part_record, 
 						      nodes);
 
-	*return_part_type = (rm_partition_t*) malloc(sizeof(rm_partition_t));
+	*return_part_type = (rm_partition_t*) xmalloc(sizeof(rm_partition_t));
 	if (!(*return_part_type)) {
 		error("_find_part_type: not enough memory for return_part_type");
 		return SLURM_ERROR;
@@ -511,9 +511,9 @@ int char2intptr(char* request, int** bl, int** tr)
 
  cleanup:
 	error("char2intptr request string insufficient dimensions");
-	free(request_tmp);
-	free(bl);
-	free(tr);
+	xfree(request_tmp);
+	xfree(bl);
+	xfree(tr);
 	bl = NULL; tr = NULL;
 	return SLURM_ERROR;
 }
@@ -528,7 +528,7 @@ int _parse_request(char* request_string, partition_t** request)
 	int *bl=NULL, *tr=NULL;
 	uint16_t *dim=NULL;
 	int i;
-	(*request) = (partition_t*) malloc(sizeof(partition_t));
+	(*request) = (partition_t*) xmalloc(sizeof(partition_t));
 	if (!(*request)) {
 		error("parse_request: not enough memory for request");
 		return SLURM_ERROR;
@@ -574,7 +574,7 @@ int _get_request_dimensions(int* bl, int* tr, uint16_t** dim)
 		return SLURM_ERROR;
 	}
 		
-	*dim = (uint16_t*) malloc(sizeof(uint16_t) * SYSTEM_DIMENSIONS);
+	*dim = (uint16_t*) xmalloc(sizeof(uint16_t) * SYSTEM_DIMENSIONS);
 	if (!(*dim)) {
 		error("get_request_dimensions: not enough memory for dim");
 		return SLURM_ERROR;
@@ -623,7 +623,7 @@ int _extract_range(char* request, char** result)
 	if (!request)
 		return 1;
 	if (!(*result)) {
-		*result = (char*) malloc(sizeof(RANGE_SIZE));
+		*result = (char*) xmalloc(sizeof(RANGE_SIZE));
 		if (!(*result)) {
 			error("_extract_range: not enough memory for *result");
 			return SLURM_ERROR;
@@ -652,7 +652,7 @@ int _extract_range(char* request, char** result)
 	return SLURM_SUCCESS;
 
  cleanup:
-	free(*result);
+	xfree(*result);
 	*result = NULL;
 	return SLURM_ERROR;
 }
@@ -687,7 +687,7 @@ void print_bgl_record(bgl_record_t* record)
 
 	if (record->bitmap){
 		int bitsize = 128;
-		char* bitstring = (char*) malloc(sizeof(char)*bitsize);
+		char* bitstring = (char*) xmalloc(sizeof(char)*bitsize);
 		bit_fmt(bitstring, bitsize, record->bitmap);
 		debug("\tbitmap: %s", bitstring);
 	}
@@ -953,10 +953,10 @@ int submit_job(struct job_record *job_ptr, bitstr_t *slurm_part_bitmap,
 void _print_bitmap(bitstr_t* bitmap)
 {
 	int bitsize = 128;
-	char* bitstring = (char*) malloc(sizeof(char)*bitsize);
+	char* bitstring = (char*) xmalloc(sizeof(char)*bitsize);
 	bit_fmt(bitstring, bitsize, bitmap);
 	debug("bitmap:\t%s", bitstring);
-	free(bitstring);
+	xfree(bitstring);
 }
 
 /** 
@@ -993,6 +993,8 @@ void update_bgl_node_bitmap(bitstr_t* bitmap)
 		    rm_get_data(my_bp,RM_BPState,&bp_state);
 		    /* from here we either update the node or bitmap
 		       entry */
+		    if ()
+
 	  }
 	  
 #endif
diff --git a/src/plugins/select/bluegene/partition_sys.c b/src/plugins/select/bluegene/partition_sys.c
index b3f941a5f5e..6a9ecd60d8e 100755
--- a/src/plugins/select/bluegene/partition_sys.c
+++ b/src/plugins/select/bluegene/partition_sys.c
@@ -239,7 +239,7 @@ int fit_request(List sys, List allocated, uint16_t* request)
 	debug("");
 	uint16_t* new_request;
 	rotate_part(request, &new_request);
-	free(request);
+	xfree(request);
 	request = new_request;
 
 	/** */
@@ -684,7 +684,7 @@ int configure_switches(rm_partition_t* partition, partition_t* partition)
 
 #else 
 
-	bgl_part_id = (pm_partition_id_t*) malloc(sizeof(pm_partition_id_t));
+	bgl_part_id = (pm_partition_id_t*) xmalloc(sizeof(pm_partition_id_t));
 	// *bgl_part_id = (int)(rand()%100);
 	*bgl_part_id = BGL_PARTITION_NUMBER++;
 	bgl_record_t* bgl_rec = (bgl_record_t*) partition->bgl_record_ptr;
@@ -782,7 +782,7 @@ void rotate_part(const uint16_t* config, uint16_t** new_config)
 		return;
 
 	if (*new_config != NULL){
-		free(*new_config);
+		xfree(*new_config);
 	}
 
 	(*new_config) = (uint16_t*) calloc(SYSTEM_DIMENSIONS, sizeof(uint16_t));
diff --git a/src/plugins/select/bluegene/select_bluegene.c b/src/plugins/select/bluegene/select_bluegene.c
index 5a6920c6a65..ad742774ebd 100644
--- a/src/plugins/select/bluegene/select_bluegene.c
+++ b/src/plugins/select/bluegene/select_bluegene.c
@@ -40,14 +40,6 @@
 #include <slurm/slurm_errno.h>
 
 #include "src/common/slurm_xlator.h"
-
-/*
-#include "src/common/list.h"
-#include "src/common/plugin.h"
-
-#include "src/common/log.h"
-#include "src/common/macros.h"
-*/
 #include "src/slurmctld/slurmctld.h"
 
 #ifdef WITH_PTHREADS
@@ -171,7 +163,8 @@ extern int select_p_node_init(struct node_record *node_ptr, int node_cnt)
 
 	// error("select/bluegene plugin not yet functional");
 	debug("select_p_node_init should be doing a system wide status "
-	      "check on all the nodes to updated the system bitmap.");
+	      "check on all the nodes to updated the system bitmap, "
+	      "along with killing old jobs, etc");
 	// return SLURM_ERROR;
 	return SLURM_SUCCESS;
 }
diff --git a/src/slurmctld/job_mgr.c b/src/slurmctld/job_mgr.c
index 7b7f3fe27d9..5e09a687fe5 100644
--- a/src/slurmctld/job_mgr.c
+++ b/src/slurmctld/job_mgr.c
@@ -2089,6 +2089,15 @@ _copy_job_desc_to_job_record(job_desc_msg_t * job_desc,
 		detail_ptr->out = xstrdup(job_desc->out);
 	if (job_desc->work_dir)
 		detail_ptr->work_dir = xstrdup(job_desc->work_dir);
+	if (job_desc->geometry){
+		int i=0;
+		for (; i<SYSTEM_DIMENSIONS; i++)
+			job_ptr->geometry[i] = job_desc->geometry[i];
+	}
+	if (job_desc->type)
+		job_ptr->type = job_desc->type;
+	if (job_desc->rotate)
+		job_ptr->rotate = job_desc->rotate;
 
 	*job_rec_ptr = job_ptr;
 	return SLURM_SUCCESS;
@@ -2274,6 +2283,14 @@ static int _validate_job_desc(job_desc_msg_t * job_desc_msg, int allocate,
 		job_desc_msg->shared = 0;	/* default not shared nodes */
 	if (job_desc_msg->min_procs == NO_VAL)
 		job_desc_msg->min_procs = 1;	/* default 1 cpu per node */
+	if (job_desc_msg->geometry[0] == (uint16_t) NO_VAL)
+		job_desc_msg->geometry[0] = 0;  /* this will indicate that geometry doesn't matter */
+	if (job_desc_msg->type == (uint16_t) NO_VAL)
+		job_desc_msg->type = RM_NAV;    /* default to try TORUS, then MESH */
+	if (job_desc_msg->rotate == (uint16_t) NO_VAL)
+		job_desc_msg->rotate = true;    /* default to allow rotate */
+	debug("validate after job_mgr type %d rotate %d RM_NAV %d NOVAL %d", job_desc_msg->type, job_desc_msg->rotate, RM_NAV, NO_VAL);
+
 	return SLURM_SUCCESS;
 }
 
@@ -3036,6 +3053,20 @@ int update_job(job_desc_msg_t * job_specs, uid_t uid)
 			job_ptr->dependency = job_specs->dependency;
 	}
 
+	if (job_specs->geometry[0] != NO_VAL) {
+		int i;
+		for (i=0; i<SYSTEM_DIMENSIONS; i++)
+			job_ptr->geometry[i] = job_specs->geometry[i];
+	}
+
+	if (job_specs->type != NO_VAL) {
+		job_ptr->type = job_specs->type;
+	}
+
+	if (job_specs->rotate != NO_VAL) {
+		job_ptr->rotate = job_specs->rotate;
+	}
+
 	return error_code;
 }
 
diff --git a/src/slurmctld/proc_req.c b/src/slurmctld/proc_req.c
index 68203b2e184..35b9a7ff126 100644
--- a/src/slurmctld/proc_req.c
+++ b/src/slurmctld/proc_req.c
@@ -118,7 +118,6 @@ inline void diff_tv_str(struct timeval *tv1,struct timeval *tv2,
  */
 void slurmctld_req (slurm_msg_t * msg)
 {
-
 	switch (msg->msg_type) {
 	case REQUEST_RESOURCE_ALLOCATION:
 		_slurm_rpc_allocate_resources(msg);
@@ -1440,6 +1439,7 @@ static void _slurm_rpc_submit_batch_job(slurm_msg_t * msg)
 	slurm_msg_t response_msg;
 	submit_response_msg_t submit_msg;
 	job_desc_msg_t *job_desc_msg = (job_desc_msg_t *) msg->data;
+
 	/* Locks: Write job, read node, read partition */
 	slurmctld_lock_t job_write_lock = { 
 		NO_LOCK, WRITE_LOCK, READ_LOCK, READ_LOCK };
diff --git a/src/slurmctld/slurmctld.h b/src/slurmctld/slurmctld.h
index d89f5c80d1d..2f6f8cd2cbc 100644
--- a/src/slurmctld/slurmctld.h
+++ b/src/slurmctld/slurmctld.h
@@ -275,6 +275,9 @@ struct job_record {
 	uint16_t kill_on_step_done;	/* 1 if job should be killed when 
 					 * the job step completes, 2 if kill
 					 * in progress */
+	uint16_t geometry[SYSTEM_DIMENSIONS]; /* geometry of the requested job */
+	uint16_t type;			 /* type of connection for request */
+	bool rotate;			 /* allow rotation of request?	  */
 	char *nodes;			/* list of nodes allocated to job */
 	bitstr_t *node_bitmap;		/* bitmap of nodes allocated to job */
 	uint32_t num_procs;		/* count of required/allocated processors */
diff --git a/src/srun/allocate.c b/src/srun/allocate.c
index be88b964d5e..6c76542ce54 100644
--- a/src/srun/allocate.c
+++ b/src/srun/allocate.c
@@ -370,6 +370,52 @@ job_desc_msg_create_from_opts (char *script)
 
 	if (opt.hold)
 		j->priority     = 0;
+
+	if (opt.geometry) {
+		char* token, *delimiter = ",x", *next_ptr;
+		int i;
+		char* geometry_tmp = xstrdup(opt.geometry);
+		char* original_ptr = geometry_tmp;
+		token = strtok_r(geometry_tmp, delimiter, &next_ptr);
+		for (i=0; i<SYSTEM_DIMENSIONS; i++){
+			
+			/* this shouldn't happen, as we've checked 
+			 * this before, but the error checking done here is simply for
+			 * redundancy */
+			if (token == NULL){
+				error("_opt_verify: not enough dimensions specified in geometry.\n");
+				/* FIXME: we shouldn't ever get this far...
+				 * so if we break here, that means we have too many
+				 * dimensions in the job, which was supposed to be
+				 * caught before in _opt_verify, so... */
+				break;
+			}
+			j->geometry[i]    = atoi(token);
+			geometry_tmp = next_ptr;
+			token = strtok_r(geometry_tmp, delimiter, &next_ptr);
+		}
+		if (original_ptr)
+			xfree(original_ptr);
+	} else {
+		j->geometry[0] = NO_VAL;
+	}
+
+	if (opt.type){
+		if (!strcasecmp(opt.type,"TORUS")) {
+			j->type = RM_TORUS;
+		} else if (!strcasecmp(opt.type,"NAV")) {
+			j->type = RM_NAV;
+		} else {
+			j->type = RM_MESH;
+		}
+	} else {
+		j->type = NO_VAL;
+	}
+	if (opt.rotate)
+		j->rotate = opt.rotate;
+	else
+		j->rotate = NO_VAL;
+
 	if (opt.max_nodes)
 		j->max_nodes    = opt.max_nodes;
 	if (opt.mincpus > -1)
@@ -397,6 +443,19 @@ job_desc_msg_create_from_opts (char *script)
 	else
 		j->host = NULL;
 
+	debug("srun phung: job request:");
+	debug("\tgeometry %d %d %d", j->geometry[0],j->geometry[1],j->geometry[2]);
+	if (j->type == 0) {
+		debug("\ttype RM_MESH");
+	} else if (j->type == 1) {
+		debug("\ttype RM_TORUS");
+	} else {
+		debug("\ttype RM_NAV");
+	}
+	debug("\trotate %d", j->rotate);
+	debug("\tmin_nodes %d", j->min_nodes);
+	debug("\tmax_nodes %d", j->max_nodes);
+
 	if (script) {
 		/*
 		 * If script is set then we are building a request for
diff --git a/src/srun/opt.c b/src/srun/opt.c
index efb27ae84cb..3a4f5b6ffa6 100644
--- a/src/srun/opt.c
+++ b/src/srun/opt.c
@@ -92,6 +92,7 @@
 #define LONG_OPT_CORE	  0x10e
 #define LONG_OPT_NOSHELL  0x10f
 #define LONG_OPT_DEBUG_TS 0x110
+#define LONG_OPT_TYPE	  0x111
 /*---- forward declarations of static functions  ----*/
 
 typedef struct env_vars env_vars_t;
@@ -422,6 +423,10 @@ static void _opt_default()
 	opt.max_exit_timeout= 60; /* Warn user 60 seconds after task exit */
 	opt.msg_timeout     = 5;  /* Default launch msg timeout           */
 
+	opt.geometry	    = NULL;
+	opt.rotate	    = (uint16_t) NO_VAL;
+	opt.type	    = NULL;
+
 	opt.euid	    = (uid_t) -1;
 	opt.egid	    = (gid_t) -1;
 	
@@ -629,6 +634,9 @@ static void _opt_args(int argc, char **argv)
 		{"wait",          required_argument, 0, 'W'},
 		{"exclude",       required_argument, 0, 'x'},
 		{"no-allocate",   no_argument,       0, 'Z'},
+		{"geometry",	  required_argument, 0, 'g'}, 
+		{"rotate",	  required_argument, 0, 'R'}, 
+		{"conn-type",	  required_argument, 0, LONG_OPT_TYPE},
 		{"quit-on-interrupt", no_argument,   0, 'q'},
 		{"quiet",            no_argument,    0, 'Q'},
 		{"contiguous",       no_argument,       0, LONG_OPT_CONT},
@@ -650,7 +658,7 @@ static void _opt_args(int argc, char **argv)
 		{NULL,               0,                 0, 0}
 	};
 	char *opt_string = "+a:Abc:C:d:D:e:Hi:IjJ:klm:n:N:"
-		"o:Op:P:Qr:st:T:uU:vVw:W:x:Zq";
+		"o:Op:P:Qr:st:T:uU:vVw:W:x:Zqg:R:";
 	char **rest = NULL;
 
 	opt.progname = xbasename(argv[0]);
@@ -711,6 +719,10 @@ static void _opt_args(int argc, char **argv)
 			xfree(opt.efname);
 			opt.efname = xstrdup(optarg);
 			break;
+		case (int)'g':
+			xfree(opt.geometry);
+			opt.geometry = xstrdup(optarg);
+			break;
 		case (int)'H':
 			opt.hold = true;
 			break;
@@ -782,6 +794,9 @@ static void _opt_args(int argc, char **argv)
 			xfree(opt.relative);
 			opt.relative = xstrdup(optarg);
 			break;
+		case (int)'R':
+			opt.rotate = _get_int(optarg, "rotate");
+			break;
 		case (int)'s':
 			opt.share = true;
 			break;
@@ -898,6 +913,10 @@ static void _opt_args(int argc, char **argv)
 		case LONG_OPT_USAGE:
 			_usage();
 			exit(0);
+		case LONG_OPT_TYPE:
+			xfree(opt.type);
+			opt.type = xstrdup(optarg);
+			break;
 		}
 	}
 
@@ -1080,6 +1099,60 @@ static bool _opt_verify(void)
 		verified = false;
 	}
 
+	/* 
+	 * -geometry must be less than or equal to SYSTEM_DIMENSIONS
+	 */
+	if (opt.geometry != NULL){
+	  char* delimiter = ",x", *next_ptr;
+	  char* geometry_str = xstrdup(opt.geometry);
+	  char* token = strtok_r(geometry_str, delimiter, &next_ptr);
+	  
+	  /* X-dimension */
+	  if (!token || atoi(token) > X_DIMENSION){
+		  error("_opt_verify: specified geometry not enough dimensions or X dimension too big");
+		  verified = false;
+	  }
+	  geometry_str = next_ptr;
+	  token = strtok_r(geometry_str, delimiter, &next_ptr);
+	  
+	  /* Y-dimension */
+	  if (!token || atoi(token) > Y_DIMENSION){
+		  error("_opt_verify: specified geometry not enough dimensions or Y dimension too big");
+		  verified = false;
+	  }
+	  geometry_str = next_ptr;
+	  token = strtok_r(geometry_str, delimiter, &next_ptr);
+
+	  /* Z-dimension */
+	  if (!token || atoi(token) > Z_DIMENSION){
+		  error("_opt_verify: specified geometry not enough dimensions or Z dimension too big");
+		  verified = false;
+	  }
+	  geometry_str = next_ptr;
+	  token = strtok_r(geometry_str, delimiter, &next_ptr);
+
+	  /* if we've read through SYSTEM_DIMENSIONS, and still have
+	     more tokens, then we have too many */
+	  if (token != NULL) {
+		  error("_opt_verify: specified geometry exceeds number of dimensions in system.");
+		  verified = false;
+	  }
+	}
+	
+	if (opt.type && 
+	    strcasecmp(opt.type,"MESH") &&
+	    strcasecmp(opt.type,"TORUS") &&
+	    strcasecmp(opt.type,"NAV")){
+		error("_opt_verify: specified conn-type \"%s\" invalid.", opt.type);
+		verified = false;
+	}
+
+	if (opt.rotate != true && opt.rotate != false){
+		error("_opt_verify: rotate <%d> must be either %d or %d for false or true, respectively.",
+		      opt.rotate, false, true);
+		verified = false;
+	}
+
 	return verified;
 }
 
@@ -1338,6 +1411,13 @@ static void _help(void)
 "      --usage                 display brief usage message\n"
 "\n"
 "Other options:\n"
-"  -V, --version               output version information and exit\n");
+"  -V, --version               output version information and exit\n"
+"\n"
+"BGL related options:\n"
+"  -g, --geometry              geometry constraints of the job.\n"
+"  -R, --rotate                allow geometry rotation (default=true)\n"
+"      --conn-type             constraint on type of connection (Mesh/Torus).\n"
+"                              If not set, then tries to fit Torus else Mesh.\n"
+);
 
 }
diff --git a/src/srun/opt.h b/src/srun/opt.h
index a92a0095f44..7537c85b53f 100644
--- a/src/srun/opt.h
+++ b/src/srun/opt.h
@@ -153,6 +153,9 @@ typedef struct srun_options {
 	int  max_exit_timeout;  /* Undocumented                 */
 	int  msg_timeout;       /* Undocumented                 */
 
+	char *geometry;		/* --geometry -g		*/
+	bool rotate;		/* --rotate -R			*/
+	char *type;		/* --type 			*/
 } opt_t;
 
 opt_t opt;
diff --git a/src/srun/srun.c b/src/srun/srun.c
index 2a04f684f86..ac7a1a7242d 100644
--- a/src/srun/srun.c
+++ b/src/srun/srun.c
@@ -127,7 +127,6 @@ int srun(int ac, char **av)
 
 	if (!opt.allocate)
 		(void) _set_rlimit_env();
-
 	/* Set up slurmctld message handler */
 	slurmctld_msg_init();
 
-- 
GitLab