From c9b4d6e0dd2e375d43e5fa9dac5f8f2c74e403ff Mon Sep 17 00:00:00 2001
From: Moe Jette <jette1@llnl.gov>
Date: Tue, 5 Oct 2004 17:40:33 +0000
Subject: [PATCH] Add support in select/bluegene plugin for node-use
 configuration parameter.

---
 doc/man/man1/smap.1                         |   5 +-
 doc/man/man5/slurm.conf.5                   |   6 +-
 slurm/slurm.h.in                            |   4 +-
 src/common/node_select.c                    |   2 +-
 src/plugins/select/bluegene/bluegene.c      | 185 ++++++++++++--------
 src/plugins/select/bluegene/bluegene.conf   |  14 +-
 src/plugins/select/bluegene/bluegene.h      |  14 +-
 src/plugins/select/bluegene/partition_sys.h |   3 +-
 src/scontrol/scontrol.c                     |   4 +-
 src/slurmctld/job_mgr.c                     |  18 +-
 src/srun/opt.c                              |   4 +-
 11 files changed, 150 insertions(+), 109 deletions(-)

diff --git a/doc/man/man1/smap.1 b/doc/man/man1/smap.1
index afcf5b24e43..8e8c305be4d 100644
--- a/doc/man/man1/smap.1
+++ b/doc/man/man1/smap.1
@@ -1,4 +1,4 @@
-.TH SMAP "1" "November 2004" "smap 0.4" "Slurm components"
+.TH SMAP "1" "October 2004" "smap 0.4" "Slurm components"
 
 .SH "NAME"
 smap \- graphically view information about SLURM jobs, partitions, and set 
@@ -56,6 +56,7 @@ Print version information and exit.
 .TP
 \fBAVAIL\fR
 Partition state: \fBup\fR or \fBdown\fR.
+.TP
 \fBTIMELIMIT\fR
 Maximum time limit for any user job in
 days:hours:minutes:seconds.  \fBinfinite\fR is used to identify
@@ -138,7 +139,7 @@ has not yet been determined.
 .ec
 
 .SH "COPYING"
-Copyright (C) 2002 The Regents of the University of California.
+Copyright (C) 2004 The Regents of the University of California.
 Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
 UCRL-CODE-2002-040.
 .LP
diff --git a/doc/man/man5/slurm.conf.5 b/doc/man/man5/slurm.conf.5
index ba4af43a595..40987b6de56 100644
--- a/doc/man/man5/slurm.conf.5
+++ b/doc/man/man5/slurm.conf.5
@@ -1,4 +1,4 @@
-.TH "slurm.conf" "5" "September 2004" "slurm.conf 0.4" "Slurm configuration file"
+.TH "slurm.conf" "5" "October 2004" "slurm.conf 0.4" "Slurm configuration file"
 .SH "NAME"
 slurm.conf \- Slurm configuration file 
 .SH "DESCRIPTION"
@@ -303,7 +303,9 @@ A value of zero indicates the node should never be set DOWN if not responding.
 Fully qualified pathname of a directory into which the SLURM controller, 
 \fBslurmctld\fR, saves its state (e.g. "/usr/local/slurm/checkpoint"). 
 SLURM state will saved here to recover from system failures.
-\fBSlurmUser\fR must be able to create files in this directory. 
+\fBSlurmUser\fR must be able to create files in this directory.
+If you have a \fBBackupController\fR configured, this location should be 
+readable and writable by both systems. 
 The default value is "/tmp".
 If any slurm daemons terminate abnormally, their core files will also be written 
 into this directory.
diff --git a/slurm/slurm.h.in b/slurm/slurm.h.in
index bec5c150746..3fbc5b24cf3 100644
--- a/slurm/slurm.h.in
+++ b/slurm/slurm.h.in
@@ -164,8 +164,8 @@ enum connection_type {
 };
 
 enum node_use_type {
-	RM_VIRTUAL,		/* application uses both processors */
-	RM_COPROCESSOR		/* use second processor for communications */
+	RM_PARTITION_COPROCESSOR_MODE, /* use extra processor for communications */
+	RM_PARTITION_VIRTUAL_NODE_MODE	/* application uses both processors */
 };
 
 enum select_data_type {
diff --git a/src/common/node_select.c b/src/common/node_select.c
index 5a68389b0c0..2032f76e1c8 100644
--- a/src/common/node_select.c
+++ b/src/common/node_select.c
@@ -338,7 +338,7 @@ static char *_job_conn_type_string(uint16_t inx)
 
 static char *_job_node_use_string(uint16_t inx)
 {
-	if (inx == RM_COPROCESSOR)
+	if (inx == RM_PARTITION_COPROCESSOR_MODE)
 		return "coprocessor";
 	else
 		return "virtual";
diff --git a/src/plugins/select/bluegene/bluegene.c b/src/plugins/select/bluegene/bluegene.c
index 749c174b166..f9b02193b18 100644
--- a/src/plugins/select/bluegene/bluegene.c
+++ b/src/plugins/select/bluegene/bluegene.c
@@ -68,7 +68,7 @@ static void _destroy_bgl_conf_record(void* object);
 static void _print_bitmap(bitstr_t* bitmap);
 static void _process_config();
 static int _parse_bgl_spec(char *in_line);
-static void _find_part_type(char* nodes, rm_partition_t** return_part_type);
+static bgl_conf_record_t* _find_config_by_nodes(char* nodes);
 static int _listfindf_conf_part_record(bgl_conf_record_t* record, char *nodes);
 static void _update_bgl_node_bitmap();
 static void _diff_tv_str(struct timeval *tv1,struct timeval *tv2,
@@ -162,7 +162,8 @@ static void _process_config()
 			 * copy_slurm_partition_list
 			 */
 			request_result->bgl_record_ptr = bgl_part;
-			request_result->part_type = (rm_partition_t*) bgl_part->part_type;
+			request_result->node_use = bgl_part->node_use;
+			request_result->part_type = bgl_part->part_type;
 			bgl_part->alloc_part = request_result;
 		}
 	}
@@ -203,13 +204,21 @@ static int _copy_slurm_partition_list(List slurm_part_list)
 		 * several bgl partitions, so we need to find how to
 		 * wire each of those bgl partitions.
 		 */
-		while(cur_nodes != NULL){
+		while (cur_nodes != NULL) {
+			bgl_conf_record_t *config_ptr;
+			config_ptr = _find_config_by_nodes(cur_nodes);
+			if (config_ptr == NULL) {
+				error("Nodes missing from bluegene.conf: %s", cur_nodes);
+				rc = SLURM_ERROR;
+				goto cleanup;
+			}
+
 			bgl_record = (bgl_record_t*) xmalloc(sizeof(bgl_record_t));
 			bgl_record->nodes = xstrdup(cur_nodes);
 			bgl_record->slurm_part_id = xstrdup(slurm_part->name);
-			bgl_record->part_type = (rm_partition_t*) xmalloc(sizeof(rm_partition_t));
 
-			_find_part_type(cur_nodes, &bgl_record->part_type);
+			bgl_record->node_use = config_ptr->node_use;
+			bgl_record->part_type = config_ptr->part_type;
 			bgl_record->hostlist = hostlist_create(cur_nodes);
 			bgl_record->size = hostlist_count(bgl_record->hostlist);
 			if (node_name2bitmap(cur_nodes, false, &(bgl_record->bitmap))){
@@ -219,15 +228,15 @@ static int _copy_slurm_partition_list(List slurm_part_list)
 				rc = SLURM_ERROR;
 				goto cleanup;
 			}
-			
-			if (slurm_part->min_nodes == slurm_part->max_nodes && 
-			    bgl_record->size == slurm_part->max_nodes)
+	
+			if ((slurm_part->min_nodes == slurm_part->max_nodes)
+			&& (bgl_record->size == slurm_part->max_nodes))
 				bgl_record->part_lifecycle = STATIC;
 			else 
 				bgl_record->part_lifecycle = DYNAMIC;
 			print_bgl_record(bgl_record);
 			list_push(bgl_list, bgl_record);
-			
+
 			nodes_tmp = next_ptr;
 			cur_nodes = strtok_r(nodes_tmp, delimiter, &next_ptr);
 		} /* end while(cur_nodes) */
@@ -294,9 +303,7 @@ extern int read_bgl_conf()
 		
 		/* parse what is left, non-comments */
 		/* partition configuration parameters */
-		if ((error_code = _parse_bgl_spec(in_line))) {
-			error("_parse_bgl_spec error, skipping this line");
-		}
+		error_code = _parse_bgl_spec(in_line);
 		
 		/* report any leftover strings on input line */
 		report_leftover(in_line, line_num);
@@ -326,45 +333,66 @@ extern int read_bgl_conf()
 static int _parse_bgl_spec(char *in_line)
 {
 	int error_code = SLURM_SUCCESS;
-	char *nodes = NULL, *part_type = NULL;
+	char *nodes = NULL, *node_use = NULL, *part_type = NULL;
 	bgl_conf_record_t* new_record;
 
 	error_code = slurm_parser(in_line,
-				  "Nodes=", 's', &nodes,
-				  "Type=", 's', &part_type,
-				  "END");
-
-	/** error if you're not specifying nodes or partition type on
-	    this line */
-	if (error_code || !nodes || !part_type){
-		xfree(nodes);
-		xfree(part_type);
-		return error_code;
-	}
+				"Nodes=", 's', &nodes,
+				"Type=", 's', &part_type,
+				"Use=", 's', &node_use,
+				"END");
 
-	// debug("parsed nodes %s", nodes);
-	// debug("partition type %s", part_type);
+	if (error_code)
+		goto cleanup;
+	if (!nodes && !node_use && !part_type)
+		goto cleanup;	/* only comment */
+	if (!nodes && (node_use || part_type)) {
+		error("bluegene.conf lacks Nodes value, but has Type or Use value");
+		error_code = SLURM_ERROR;
+		goto cleanup;
+	}
 
 	new_record = (bgl_conf_record_t*) xmalloc(sizeof(bgl_conf_record_t));
 	new_record->nodes = nodes;
-	new_record->part_type = xmalloc(sizeof(rm_partition_t));
+	nodes = NULL;	/* pointer moved, nothing left to xfree */
 
-	if (strcasecmp(part_type, "TORUS") == 0)
-		*(new_record->part_type) = RM_TORUS;
+	if (!part_type)
+		new_record->part_type = RM_MESH;
+	else if (strcasecmp(part_type, "TORUS") == 0)
+		new_record->part_type = RM_TORUS;
 	else if (strcasecmp(part_type, "MESH") == 0)
-		*(new_record->part_type) = RM_MESH;
+		new_record->part_type = RM_MESH;
+	else {
+		error("_parse_bgl_spec: partition type %s invalid for nodes %s, "
+			"defaulting to type: MESH", part_type, new_record->nodes);
+		new_record->part_type = RM_MESH;
+	}
+
+	if (!node_use)
+		new_record->node_use = RM_PARTITION_COPROCESSOR_MODE;
+	else if (strcasecmp(node_use, "COPROCESSOR") == 0)
+		new_record->node_use = RM_PARTITION_COPROCESSOR_MODE;
+	else if (strcasecmp(node_use, "VIRTUAL") == 0)
+		new_record->node_use = RM_PARTITION_VIRTUAL_NODE_MODE;
 	else {
-		error("_parse_bgl_spec: partition type %s invalid for nodes %s",
-		      part_type, nodes);
-		error("defaulting to type: MESH");
-		*(new_record->part_type) = RM_MESH;
+		error("_parse_bgl_spec: node use %s invalid for nodes %s, "
+			"defaulting to type: COPROCESSOR", 
+			node_use, new_record->nodes);
+		new_record->node_use = RM_PARTITION_COPROCESSOR_MODE;
 	}
 	list_push(bgl_conf_list, new_record);
 
+#if _DEBUG
+	debug("_parse_bgl_spec: added nodes=%s type=%s use=%s", 
+		new_record->nodes, convert_part_type(new_record->part_type), 
+		convert_node_use(new_record->node_use));
+#endif
+
+  cleanup:
 	xfree(part_type);
-	/* xfree(nodes);	Don't do this as we moved value into new record type */
-	
-	return SLURM_SUCCESS;
+	xfree(node_use);
+	xfree(nodes);
+	return error_code;
 }
 
 static void _destroy_bgl_record(void* object)
@@ -374,7 +402,6 @@ static void _destroy_bgl_record(void* object)
 	if (this_record){
 		xfree(this_record->nodes);
 		xfree(this_record->slurm_part_id);
-		xfree(this_record->part_type);
 		if (this_record->hostlist)
 			hostlist_destroy(this_record->hostlist);
 		if (this_record->bitmap)
@@ -391,31 +418,19 @@ static void _destroy_bgl_conf_record(void* object)
 	bgl_conf_record_t* this_record = (bgl_conf_record_t*) object;
 	if (this_record){
 		xfree(this_record->nodes);
-		xfree(this_record->part_type);
 		xfree(this_record);
 	}
 }
 
 /** 
- * search through the list of nodes,types to find the partition type
- * for the given nodes
+ * search through the list of nodes,types to find the partition 
+ * containing the given nodes
  */
-static void _find_part_type(char* nodes, rm_partition_t** return_part_type)
+static bgl_conf_record_t* _find_config_by_nodes(char* nodes)
 {
-	bgl_conf_record_t* record = NULL;
-
-	record = (bgl_conf_record_t*) list_find_first(bgl_conf_list,
+	return (bgl_conf_record_t*) list_find_first(bgl_conf_list,
 						      (ListFindF) _listfindf_conf_part_record, 
 						      nodes);
-
-	*return_part_type = (rm_partition_t*) xmalloc(sizeof(rm_partition_t));
-
-	if (record != NULL && record->part_type != NULL){
-		**return_part_type = *(record->part_type);
-	} else {
-		// error("warning: nodes not found in slurm.conf, defaulting to type RM_MESH");
-		**return_part_type = RM_MESH;
-	}
 }
 
 /** nodes example: 000x111 */
@@ -535,6 +550,7 @@ extern void print_bgl_record(bgl_record_t* record)
 	info("\tsize: %d", record->size);
 	info("\tlifecycle: %s", convert_lifecycle(record->part_lifecycle));
 	info("\tpart_type: %s", convert_part_type(record->part_type));
+	info("\tnode_use: %s", convert_node_use(record->node_use));
 
 	if (record->hostlist){
 		char buffer[BUFSIZE];
@@ -565,18 +581,30 @@ extern char* convert_lifecycle(lifecycle_type_t lifecycle)
 		return "STATIC";
 }
 
-extern char* convert_part_type(rm_partition_t* pt)
+extern char* convert_part_type(rm_partition_t pt)
 {
-	switch(*pt) {
-	case (RM_MESH): 
-		return "RM_MESH"; 
-	case (RM_TORUS): 
-		return "RM_TORUS"; 
-	case (RM_NAV):
-		return "RM_NAV";
-		      
-	default:
-		break;
+	switch (pt) {
+		case (RM_MESH): 
+			return "RM_MESH"; 
+		case (RM_TORUS): 
+			return "RM_TORUS"; 
+		case (RM_NAV):
+			return "RM_NAV";
+		default:
+			break;
+	}
+	return "";
+}
+
+extern char* convert_node_use(rm_partition_mode_t pt)
+{
+	switch (pt) {
+		case (RM_PARTITION_COPROCESSOR_MODE): 
+			return "RM_COPROCESSOR"; 
+		case (RM_PARTITION_VIRTUAL_NODE_MODE): 
+			return "RM_VIRTUAL"; 
+		default:
+			break;
 	}
 	return "";
 }
@@ -656,18 +684,27 @@ static int _find_best_partition_match(struct job_record* job_ptr,
 		/***********************************************/
 		/* check the connection type specified matches */
 		/***********************************************/
-		// debug("part type match %s ? %s", convert_part_type(&job_ptr->type), 
-		// convert_part_type(record->part_type));
-		if (!record->part_type){
-			error("find_best_partition_match record->part_type is NULL"); 
-			continue;
-		}
-		debug("conn_type %d", conn_type);
-		if (conn_type != *(record->part_type) &&
-		    conn_type != RM_NAV){
+#if _DEBUG
+		info("part type match %s ? %s", convert_part_type(conn_type), 
+			convert_part_type(record->part_type));
+#endif
+
+		if ((conn_type != record->part_type)
+		&& (conn_type != RM_NAV)) {
 			continue;
 		} 
 
+		/***********************************************/
+		/* check the node_use specified matches */
+		/***********************************************/
+#if _DEBUG
+		info("node use match %s ? %s", convert_node_use(node_use), 
+			convert_node_use(record->node_use));
+#endif
+
+		if (node_use != record->node_use)
+			continue;
+
 		/*****************************************/
 		/** match up geometry as "best" possible */
 		/*****************************************/
diff --git a/src/plugins/select/bluegene/bluegene.conf b/src/plugins/select/bluegene/bluegene.conf
index 7ddcd23119f..c5ae76adfe2 100644
--- a/src/plugins/select/bluegene/bluegene.conf
+++ b/src/plugins/select/bluegene/bluegene.conf
@@ -1,9 +1,9 @@
-
 # Sample Bluegene/L plugin configuration file.  See README for
-# description.  the BGL parititon nodes must match preconfigured SLURM
-# partitions.
+# description.  The BGL parititon nodes must match preconfigured SLURM
+# partitions. Default value for Type is Mesh. Default value for Use 
+# is Coprocessor.
 
-Nodes=bgl[400x511] Type=Mesh
-Nodes=bgl[600x711] Type=Torus
-Nodes=bgl[422x531] Type=Torus
-Nodes=bgl[622x731] Type=Mesh
+Nodes=bgl[400x511] Type=Mesh Use=Virtual
+Nodes=bgl[600x711] Type=Torus Use=Virtual
+Nodes=bgl[422x531] Type=Torus Use=Coprocessor
+Nodes=bgl[622x731] Type=Mesh Use=Coprocessor
diff --git a/src/plugins/select/bluegene/bluegene.h b/src/plugins/select/bluegene/bluegene.h
index e5c2eadd412..4ccf1d71e2f 100644
--- a/src/plugins/select/bluegene/bluegene.h
+++ b/src/plugins/select/bluegene/bluegene.h
@@ -38,6 +38,7 @@
 #ifndef _RM_API_H__
   typedef uint16_t pm_partition_id_t;
   typedef uint16_t rm_partition_t;
+  typedef uint16_t rm_partition_mode_t;
 #else 
   rm_BGL_t *bgl;
 #endif
@@ -54,7 +55,8 @@ typedef struct bgl_record {
 	bitstr_t *bitmap;		/* bitmap of nodes for this partition */
 	struct partition* alloc_part;       /* the allocated partition   */
 	int size;			/* node count for the partitions */
-	rm_partition_t* part_type;	/* Type=Mesh/Torus/		*/
+	rm_partition_t part_type;	/* Mesh or Torus or NAV		*/
+	rm_partition_mode_t node_use;	/* either COPROCESSOR or VIRTUAL */
 } bgl_record_t;
 
 /** 
@@ -63,7 +65,8 @@ typedef struct bgl_record {
  */
 typedef struct bgl_conf_record{
 	char* nodes;
-	rm_partition_t* part_type;
+	rm_partition_t part_type;
+	rm_partition_mode_t node_use;
 } bgl_conf_record_t;
 
 /** 
@@ -98,10 +101,11 @@ extern void sort_bgl_record_dec_size(List records);
 
 /** */
 extern void print_bgl_record(bgl_record_t* record);
-/** */
+
+/* Return strings representing blue gene data types */
 extern char* convert_lifecycle(lifecycle_type_t lifecycle);
-/** */
-extern char* convert_part_type(rm_partition_t* pt);
+extern char* convert_part_type(rm_partition_t pt);
+extern char* convert_node_use(rm_partition_mode_t pt);
 
 /* bluegene_agent - detached thread periodically updates status of bluegene nodes */
 extern void *bluegene_agent(void *args);
diff --git a/src/plugins/select/bluegene/partition_sys.h b/src/plugins/select/bluegene/partition_sys.h
index 07c3a2a33f7..51067b2c680 100644
--- a/src/plugins/select/bluegene/partition_sys.h
+++ b/src/plugins/select/bluegene/partition_sys.h
@@ -47,7 +47,8 @@ typedef struct partition{
 
 #else
 	ushort* bgl_part_id;	/* ID returned from CMCS	*/
-	ushort* part_type;	/* Type=Mesh/Torus/		*/
+	ushort part_type;	/* Type=Mesh/Torus/NAV		*/
+	ushort node_use;	/* Use=Virtual/Coprocessor	*/
 #endif
 } partition_t;
 
diff --git a/src/scontrol/scontrol.c b/src/scontrol/scontrol.c
index 10e9092e1da..ed9d62a3000 100644
--- a/src/scontrol/scontrol.c
+++ b/src/scontrol/scontrol.c
@@ -1576,9 +1576,9 @@ _update_job (int argc, char *argv[])
 		}
 		else if (strncasecmp(argv[i], "NodeUse=", 8) == 0) {
 			if (strcasecmp(&argv[i][8], "virtual") == 0)
-				job_msg.node_use = RM_VIRTUAL;
+				job_msg.node_use = RM_PARTITION_VIRTUAL_NODE_MODE;
 			else if (strcasecmp(&argv[i][8], "coprocessor") == 0)
-				job_msg.node_use = RM_COPROCESSOR;
+				job_msg.node_use = RM_PARTITION_COPROCESSOR_MODE;
 			else
 				job_msg.node_use = 
 					(uint16_t) strtol(&argv[i][8], 
diff --git a/src/slurmctld/job_mgr.c b/src/slurmctld/job_mgr.c
index e2c27e6d692..18f998e128e 100644
--- a/src/slurmctld/job_mgr.c
+++ b/src/slurmctld/job_mgr.c
@@ -2137,7 +2137,6 @@ void job_time_limit(void)
 	job_iterator = list_iterator_create(job_list);
 	while ((job_ptr =
 		(struct job_record *) list_next(job_iterator))) {
-		bool inactive_flag = false;
 		xassert (job_ptr->magic == JOB_MAGIC);
 		if (job_ptr->job_state != JOB_RUNNING)
 			continue;
@@ -2145,19 +2144,16 @@ void job_time_limit(void)
 		if (slurmctld_conf.inactive_limit && 
 		    (job_ptr->time_last_active <= old)) {
 			/* job inactive, kill it */
-			job_ptr->end_time   = now;
-			job_ptr->time_limit = 1;
-			inactive_flag       = true;
+			info("Inactivity time limit reached for JobId=%u",
+				job_ptr->job_id);
+			_job_timed_out(job_ptr);
+			continue;
 		}
 		if ((job_ptr->time_limit != INFINITE) &&
 		    (job_ptr->end_time <= now)) {
 			last_job_update = now;
-			if (inactive_flag)
-				info("Inactivity time limit reached for "
-					"JobId=%u", job_ptr->job_id);
-			else
-				info("Time limit exhausted for JobId=%u",
-					job_ptr->job_id);
+			info("Time limit exhausted for JobId=%u",
+				job_ptr->job_id);
 			_job_timed_out(job_ptr);
 			continue;
 		}
@@ -2289,7 +2285,7 @@ static int _validate_job_desc(job_desc_msg_t * job_desc_msg, int allocate,
 	if (job_desc_msg->conn_type == (uint16_t) NO_VAL)
 		job_desc_msg->conn_type = RM_NAV;  /* try TORUS, then MESH */
 	if (job_desc_msg->node_use == (uint16_t) NO_VAL)
-		job_desc_msg->node_use = RM_COPROCESSOR;
+		job_desc_msg->node_use = RM_PARTITION_COPROCESSOR_MODE;
 	if (job_desc_msg->rotate == (uint16_t) NO_VAL)
 		job_desc_msg->rotate = true;    /* default to allow rotate */
 
diff --git a/src/srun/opt.c b/src/srun/opt.c
index 62d50c6d3c2..e10d4c77d8b 100644
--- a/src/srun/opt.c
+++ b/src/srun/opt.c
@@ -257,9 +257,9 @@ static int _verify_node_use(const char *arg)
 	int len = strlen(arg);
 
 	if (!strncasecmp(arg, "VIRTUAL", len))
-		return RM_VIRTUAL;
+		return RM_PARTITION_VIRTUAL_NODE_MODE;
 	else if (!strncasecmp(arg, "COPROCESSOR", len))
-		return RM_COPROCESSOR;
+		return RM_PARTITION_COPROCESSOR_MODE;
 
 	error("invalid --node-use argument %s ignored.", arg);
 	return -1;
-- 
GitLab