diff --git a/src/slurmctld/controller.c b/src/slurmctld/controller.c index f13d6d0278115b5a3852bffe176da85f6fb45208..594d0e30f162c43c7f5bac1bfa2133d6703269fb 100644 --- a/src/slurmctld/controller.c +++ b/src/slurmctld/controller.c @@ -15,9 +15,11 @@ #include <errno.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> #include <syslog.h> #include <sys/socket.h> #include <netinet/in.h> +#include <unistd.h> #include "slurm.h" #include "slurmlib.h" @@ -27,9 +29,10 @@ int msg_from_root (void); void slurmctld_req (int sockfd); +int main (int argc, char *argv[]) { int error_code; - int child_pid, cli_len, newsockfd, sockfd; + int cli_len, newsockfd, sockfd; struct sockaddr_in cli_addr, serv_addr; char node_name[MAX_NAME_LEN]; log_options_t opts = LOG_OPTS_STDERR_ONLY; @@ -62,6 +65,7 @@ main (int argc, char *argv[]) { serv_addr.sin_port = htons (SLURMCTLD_PORT); error_code = bind (sockfd, (struct sockaddr *) &serv_addr, sizeof (serv_addr)); if ((error_code < 0) && (errno == EADDRINUSE)) { + printf("waiting to bind\n"); sleep (10); error_code = bind (sockfd, (struct sockaddr *) &serv_addr, sizeof (serv_addr)); @@ -102,7 +106,7 @@ int dump_build (char **buffer_ptr, int *buffer_size) { char *buffer; - int buffer_offset, buffer_allocated, i, record_size; + int buffer_offset, buffer_allocated; char out_line[BUILD_SIZE * 2]; buffer_ptr[0] = NULL; diff --git a/src/slurmctld/job_mgr.c b/src/slurmctld/job_mgr.c index fddd854ba734ca71cf0bf99846cff44e786d127d..225583cd07c6ed63d4ae98afba1149131ef92453 100644 --- a/src/slurmctld/job_mgr.c +++ b/src/slurmctld/job_mgr.c @@ -9,6 +9,7 @@ # include <config.h> #endif +#include <ctype.h> #include <errno.h> #include <stdio.h> #include <stdlib.h> @@ -217,7 +218,7 @@ dump_all_job (char **buffer_ptr, int *buffer_size, time_t * update_time, ListIterator job_record_iterator; struct job_record *job_record_point; char *buffer; - int buffer_offset, buffer_allocated, error_code, i, record_size; + int buffer_offset, buffer_allocated, error_code; char out_line[BUF_SIZE]; buffer_ptr[0] = NULL; @@ -238,7 +239,8 @@ dump_all_job (char **buffer_ptr, int *buffer_size, time_t * update_time, goto cleanup; /* write individual job records */ - while (job_record_point = (struct job_record *) list_next (job_record_iterator)) { + while ((job_record_point = + (struct job_record *) list_next (job_record_iterator))) { if (job_record_point->magic != JOB_MAGIC) fatal ("dump_all_job: data integrity is bad"); @@ -536,10 +538,10 @@ int job_create (char *job_specs, char **new_job_id) { char *req_features, *req_node_list, *job_name, *req_group; - char *req_partition, *script, *out_line, *job_id; + char *req_partition, *script, *job_id; int contiguous, req_cpus, req_nodes, min_cpus, min_memory; int i, min_tmp_disk, time_limit, procs_per_task, user_id; - int error_code, cpu_tally, dist, node_tally, key, shared; + int error_code, dist, key, shared; struct part_record *part_ptr; struct job_record *job_ptr; struct job_details *detail_ptr; @@ -1014,6 +1016,7 @@ parse_job_specs (char *job_specs, char **req_features, char **req_node_list, xfree (shared_str); req_features[0] = req_node_list[0] = req_group[0] = NULL; job_id[0] = req_partition[0] = job_name[0] = script[0] = NULL; + return error_code; } diff --git a/src/slurmctld/job_scheduler.c b/src/slurmctld/job_scheduler.c index 9003e76de2cb80d1405ae737a908e2c28f44e269..9c8584d2bc2580b3fbec40929f02cf7ff82f72a9 100644 --- a/src/slurmctld/job_scheduler.c +++ b/src/slurmctld/job_scheduler.c @@ -45,8 +45,8 @@ int build_job_queue (struct job_queue **job_queue) { ListIterator job_record_iterator; - struct job_record *job_record_point; - int job_buffer_size, job_queue_size, i; + struct job_record *job_record_point = NULL; + int job_buffer_size, job_queue_size; struct job_queue *my_job_queue; /* build list pending jobs */ @@ -54,7 +54,8 @@ build_job_queue (struct job_queue **job_queue) job_queue[0] = my_job_queue = NULL; job_record_iterator = list_iterator_create (job_list); - while (job_record_point = (struct job_record *) list_next (job_record_iterator)) { + while ((job_record_point = + (struct job_record *) list_next (job_record_iterator))) { if (job_record_point->job_state != JOB_PENDING) continue; if (job_record_point->magic != JOB_MAGIC) diff --git a/src/slurmctld/node_mgr.c b/src/slurmctld/node_mgr.c index 1fcee42df5a2c1edd6025a522a33810c15144cfd..c28fb9f9a65aaf9d3f07771e897386182cf77986 100644 --- a/src/slurmctld/node_mgr.c +++ b/src/slurmctld/node_mgr.c @@ -9,22 +9,21 @@ # include <config.h> #endif +#include <ctype.h> #include <errno.h> #include <stdio.h> +#include <string.h> -#include "list.h" #include "slurm.h" #include "slurmlib.h" #define BUF_SIZE 1024 -#define NO_VAL (-99) #define SEPCHARS " \n\t" List config_list = NULL; /* list of config_record entries */ struct node_record *node_record_table_ptr = NULL; /* location of the node records */ char *node_state_string[] = - { "DOWN", "UNKNOWN", "IDLE", "STAGE_IN", "BUSY", "STAGE_OUT", -"DRAINED", "DRAINING", "END" }; + { "DOWN", "UNKNOWN", "IDLE", "BUSY", "DRAINED", "DRAINING", "END" }; int *hash_table = NULL; /* table of hashed indicies into node_record */ struct config_record default_config_record; struct node_record default_node_record; @@ -38,15 +37,16 @@ bitstr_t *idle_node_bitmap = NULL; /* bitmap of nodes are idle */ int delete_config_record (); void dump_hash (); int hash_index (char *name); -void rehash (); void split_node_name (char *name, char *prefix, char *suffix, int *index, int *digits); #if DEBUG_MODULE /* main is used here for testing purposes only */ +int main (int argc, char *argv[]) { - int error_code, node_count, i, total_procs; + int error_code, node_count, i; + uint32_t total_procs; char *out_line; bitstr_t *map1, *map2, *map3; struct config_record *config_ptr; @@ -141,17 +141,26 @@ main (int argc, char *argv[]) if (strcmp (out_line, "lx[01-02],lx04") != 0) printf ("ERROR: bitmap2node_name results bad %s vs %s\n", out_line, "lx[01-02],lx04"); - build_node_list (map3, DIST_CYCLE, 6, &node_list, &total_procs); - printf("build_node_list: 6 procs/task over lx[01-02],lx04 has %d procs over %s\n", + build_node_list (map3, &node_list, &total_procs); + printf("build_node_list: lx[01-02],lx04 has %d procs over %s\n", total_procs, node_list); bit_free (map3); xfree (out_line); xfree (node_list); - update_time = (time_t) 0; error_code = validate_node_specs ("lx01", 12, 345, 67); if (error_code) printf ("ERROR: validate_node_specs error1\n"); + + printf("dumping node info\n"); + update_time = (time_t) 0; + error_code = pack_all_node (&dump, &dump_size, &update_time); + if (error_code) + printf ("ERROR: pack_all_node error %d\n", error_code); + if (dump) + xfree(dump); + + update_time = (time_t) 0; error_code = dump_all_node (&dump, &dump_size, &update_time); if (error_code) printf ("ERROR: dump_all_node error %d\n", error_code); @@ -199,7 +208,7 @@ main (int argc, char *argv[]) /* * bitmap2node_name - given a bitmap, build a list of comma separated node names. - * names may include regular expressions + * names may include regular expressions (e.g. "lx[01-10]") * input: bitmap - bitmap pointer * node_list - place to put node list * output: node_list - set to node list or NULL on error @@ -210,13 +219,11 @@ main (int argc, char *argv[]) int bitmap2node_name (bitstr_t *bitmap, char **node_list) { - int error_code, node_list_size, i; - struct node_record *node_ptr; + int node_list_size, i; char prefix[MAX_NAME_LEN], suffix[MAX_NAME_LEN]; char format[MAX_NAME_LEN], temp[MAX_NAME_LEN]; char last_prefix[MAX_NAME_LEN], last_suffix[MAX_NAME_LEN]; - int first_index, last_index, index, digits; - unsigned mask; + int first_index = 0, last_index = 0, index, digits; node_list[0] = NULL; node_list_size = 0; @@ -304,11 +311,10 @@ bitmap2node_name (bitstr_t *bitmap, char **node_list) /* - * build_node_list - build a node_list for a job laying out the actual + * build_node_list - build a node_list for a job including processor + * count on the node (e.g. "lx01[4],lx02[4],...") * task distributions on the nodes * input: bitmap - bitmap of nodes to use - * dist - distribution of tasks, BLOCK or CYCLE - * procs_per_task - how many processor each task will consume * node_list - place to store node list * total_procs - place to store count of total processors allocated * output: node_list - comma separated list of nodes on which the tasks @@ -318,55 +324,37 @@ bitmap2node_name (bitstr_t *bitmap, char **node_list) * NOTE: the storage at node_list must be xfreed by the caller */ void -build_node_list (bitstr_t *bitmap, enum task_dist dist, - int procs_per_task, char **node_list, int *total_procs) +build_node_list (bitstr_t *bitmap, char **node_list, uint32_t *total_procs) { - int i, j, node_list_size, max_procs, min_procs; - int node_proc_count, sum_procs; + int i, node_list_size; + int sum_procs; + char tmp_str[MAX_NAME_LEN+10]; *total_procs = 0; node_list[0] = NULL; node_list_size = 0; if (bitmap == NULL) fatal ("build_node_list: bitmap is NULL"); - if (procs_per_task < 0) - fatal ("build_node_list: procs_per_task invalid (%d)", - procs_per_task); node_list[0] = xmalloc (BUF_SIZE); strcpy (node_list[0], ""); sum_procs = 0; - max_procs = procs_per_task; - for (min_procs = procs_per_task; min_procs <= max_procs; - min_procs+= procs_per_task) { - for (i = 0; i < node_record_count; i++) { - if (bit_test (bitmap, i) != 1) - continue; - node_proc_count = node_record_table_ptr[i].cpus; - if (node_proc_count < min_procs) - continue; - if (min_procs == procs_per_task) - sum_procs += node_proc_count; - if (node_proc_count > max_procs) - max_procs = node_proc_count; - - if (node_list_size < - (strlen (node_list[0]) + - (MAX_NAME_LEN+1) * node_proc_count)) { - node_list_size += BUF_SIZE; - xrealloc (node_list[0], node_list_size); - } - for (j = 0; j < node_proc_count; j += procs_per_task) { - if (strlen (node_list[0]) > 0) - strcat (node_list[0], ","); - strcat (node_list[0], node_record_table_ptr[i].name); - if (dist == DIST_CYCLE) - break; - } + for (i = 0; i < node_record_count; i++) { + if (bit_test (bitmap, i) != 1) + continue; + sprintf (tmp_str, "%s[%d]", + node_record_table_ptr[i].name, + node_record_table_ptr[i].cpus); + if (node_list_size < + (strlen (node_list[0]) + (MAX_NAME_LEN+10))) { + node_list_size += BUF_SIZE; + xrealloc (node_list[0], node_list_size); } - if (dist == DIST_BLOCK) - break; + if (sum_procs > 0) + strcat (node_list[0], ","); + strcat (node_list[0], node_record_table_ptr[i].name); + sum_procs += node_record_table_ptr[i].cpus; } *total_procs = sum_procs; xrealloc (node_list[0], strlen (node_list[0]) + 1); @@ -538,7 +526,9 @@ dump_hash () /* - * dump_all_node - dump all configuration and node information to a buffer + * dump_all_node - dump all configuration and node information in text format + * to a buffer, the data format will be the same as that of a configuration + * file (and can be used as such) * input: buffer_ptr - location into which a pointer to the data is to be stored. * the data buffer is actually allocated by dump_node and the * calling function must xfree the storage. @@ -556,8 +546,8 @@ int dump_all_node (char **buffer_ptr, int *buffer_size, time_t * update_time) { char *buffer; - int buffer_offset, buffer_allocated, error_code, i, inx; - char out_line[BUF_SIZE], *feature, *partition; + int buffer_offset, buffer_allocated, error_code, inx; + char out_line[BUF_SIZE]; buffer_ptr[0] = NULL; *buffer_size = 0; @@ -578,7 +568,7 @@ dump_all_node (char **buffer_ptr, int *buffer_size, time_t * update_time) for (inx = 0; inx < node_record_count; inx++) { if ((node_record_table_ptr[inx].magic != NODE_MAGIC) || (node_record_table_ptr[inx].config_ptr->magic != CONFIG_MAGIC)) - fatal ("dump_node: data integrity is bad"); + fatal ("dump_all_node: data integrity is bad"); error_code = dump_node(&node_record_table_ptr[inx], out_line, BUF_SIZE); if (error_code != 0) continue; @@ -603,7 +593,9 @@ dump_all_node (char **buffer_ptr, int *buffer_size, time_t * update_time) /* - * dump_node - dump all configuration information about a specific node to a buffer + * dump_node - dump all configuration information about a specific node in text format + * to a buffer, the data format will be the same as that of a configuration + * file (and can be used as such) * input: dump_node_ptr - pointer to node for which information is requested * out_line - buffer for node information * out_line_size - byte size of out_line @@ -662,7 +654,6 @@ dump_node (struct node_record *dump_node_ptr, char *out_line, int out_line_size) struct node_record * find_node_record (char *name) { - struct node_record *node_record_point; /* pointer to node_record */ int i; /* try to find in hash table first */ @@ -1010,6 +1001,125 @@ node_unlock () } +/* + * pack_all_node - dump all configuration and node information for all nodes in + * machine independent form (for network transmission) + * input: buffer_ptr - location into which a pointer to the data is to be stored. + * the data buffer is actually allocated by dump_node and the + * calling function must xfree the storage. + * buffer_size - location into which the size of the created buffer is in bytes + * update_time - dump new data only if partition records updated since time + * specified, otherwise return empty buffer + * output: buffer_ptr - the pointer is set to the allocated buffer. + * buffer_size - set to size of the buffer in bytes + * update_time - set to time partition records last updated + * returns 0 if no error, errno otherwise + * global: node_record_table_ptr - pointer to global node table + * NOTE: the caller must xfree the buffer at *buffer_ptr when no longer required + */ +int +pack_all_node (char **buffer_ptr, int *buffer_size, time_t * update_time) +{ + int buf_len, buffer_allocated, buffer_offset = 0, error_code, inx; + char *buffer; + void *buf_ptr; + + buffer_ptr[0] = NULL; + *buffer_size = 0; + if (*update_time == last_node_update) + return 0; + + buffer_allocated = (BUF_SIZE*16); + buffer = xmalloc(buffer_allocated); + buf_ptr = buffer; + buf_len = buffer_allocated; + + /* write haeader: version and time */ + pack32 ((uint32_t) NODE_STRUCT_VERSION, &buf_ptr, &buf_len); + pack32 ((uint32_t) last_node_update, &buf_ptr, &buf_len); + + /* write node records */ + for (inx = 0; inx < node_record_count; inx++) { + if ((node_record_table_ptr[inx].magic != NODE_MAGIC) || + (node_record_table_ptr[inx].config_ptr->magic != CONFIG_MAGIC)) + fatal ("pack_all_node: data integrity is bad"); + + error_code = pack_node(&node_record_table_ptr[inx], &buf_ptr, &buf_len); + if (error_code != 0) continue; + if (buf_len > BUF_SIZE) + continue; + buffer_allocated += (BUF_SIZE*16); + buf_len += (BUF_SIZE*16); + buffer_offset = (char *)buf_ptr - buffer; + xrealloc(buffer, buffer_allocated); + buf_ptr = buffer + buffer_offset; + } + + if (buffer) + xrealloc (buffer, buffer_offset); + + buffer_ptr[0] = buffer; + *buffer_size = buffer_offset; + *update_time = last_node_update; + return 0; +} + + +/* + * pack_node - dump all configuration information about a specific node in + * machine independent form (for network transmission) + * input: dump_node_ptr - pointer to node for which information is requested + * buf_ptr - buffer for node information + * buf_len - byte size of buffer + * output: buf_ptr - advanced to end of data written + * buf_len - byte size remaining in buffer + * return 0 if no error, 1 if out_line buffer too small + * NOTE: if you make any changes here be sure to increment the value of NODE_STRUCT_VERSION + * and make the corresponding changes to load_node_config in api/node_info.c + */ +int +pack_node (struct node_record *dump_node_ptr, void **buf_ptr, int *buf_len) +{ + int state; + char *partition = NULL; + uint32_t feature_size, name_size, partition_size; + + state = dump_node_ptr->node_state; + if (state < 0) + state = STATE_DOWN; + name_size = strlen(dump_node_ptr->name) + 1; + + if (dump_node_ptr->config_ptr->feature) + feature_size = strlen(dump_node_ptr->config_ptr->feature) + 1; + else + feature_size = 0; + + if (dump_node_ptr->partition_ptr) { + partition = dump_node_ptr->partition_ptr->name; + partition_size = strlen(dump_node_ptr->partition_ptr->name) + 1; + } + else + partition_size = 0; + + if (name_size + feature_size + partition_size + 40 > *buf_len) { + error ("pack_node: buffer too small for node %s", dump_node_ptr->name); + return 1; + } + + packstr (dump_node_ptr->name, name_size, buf_ptr, buf_len); + pack32 (state, buf_ptr, buf_len); + pack32 (dump_node_ptr->cpus, buf_ptr, buf_len); + pack32 (dump_node_ptr->real_memory, buf_ptr, buf_len); + pack32 (dump_node_ptr->tmp_disk, buf_ptr, buf_len); + pack32 (dump_node_ptr->config_ptr->weight, buf_ptr, buf_len); + packstr (dump_node_ptr->config_ptr->feature, feature_size, + buf_ptr, buf_len); + packstr (partition, partition_size, buf_ptr, buf_len); + + return 0; +} + + /* * rehash - build a hash table of the node_record entries. this is a large hash table * to permit the immediate finding of a record based only upon its name without regards @@ -1024,7 +1134,6 @@ node_unlock () void rehash () { - struct node_record *node_record_point; /* pointer to node_record */ int i, inx; xrealloc (hash_table, (sizeof (int) * node_record_count)); @@ -1192,7 +1301,8 @@ update_node (char *node_names, char *spec) * global: node_record_table_ptr - pointer to global node table */ int -validate_node_specs (char *node_name, int cpus, int real_memory, int tmp_disk) { +validate_node_specs (char *node_name, uint32_t cpus, + uint32_t real_memory, uint32_t tmp_disk) { int error_code; struct config_record *config_ptr; struct node_record *node_ptr; diff --git a/src/slurmctld/node_scheduler.c b/src/slurmctld/node_scheduler.c index c02a15a9c19bcecae1f2cff440eb05e1008f358a..33e612f6ed11190a54d74ff3b00902b46ac58369 100644 --- a/src/slurmctld/node_scheduler.c +++ b/src/slurmctld/node_scheduler.c @@ -15,6 +15,7 @@ #include <errno.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> #include <syslog.h> #include "slurm.h" @@ -22,9 +23,9 @@ #define BUF_SIZE 1024 struct node_set { /* set of nodes with same configuration that could be allocated */ - int cpus_per_node; - int nodes; - int weight; + uint32_t cpus_per_node; + uint32_t nodes; + uint32_t weight; int feature; bitstr_t *my_bitmap; }; @@ -32,18 +33,20 @@ struct node_set { /* set of nodes with same configuration that could be allocat int pick_best_quadrics (bitstr_t *bitmap, bitstr_t *req_bitmap, int req_nodes, int req_cpus, int consecutive); int pick_best_nodes (struct node_set *node_set_ptr, int node_set_size, - bitstr_t **req_bitmap, int req_cpus, int req_nodes, - int contiguous, int shared, int max_nodes); + bitstr_t **req_bitmap, uint32_t req_cpus, uint32_t req_nodes, + int contiguous, int shared, uint32_t max_nodes); int valid_features (char *requested, char *available); #if DEBUG_MODULE /* main is used here for testing purposes only */ +int main (int argc, char *argv[]) { int error_code, line_num, i; FILE *command_file; char in_line[BUF_SIZE], *job_id, *node_list; log_options_t opts = LOG_OPTS_STDERR_ONLY; + clock_t start_time; log_init(argv[0], opts, SYSLOG_FACILITY_DAEMON, NULL); @@ -101,6 +104,7 @@ main (int argc, char *argv[]) line_num = 0; printf ("\n"); while (fgets (in_line, BUF_SIZE, command_file)) { + start_time = clock (); job_id = node_list = NULL; if (in_line[strlen (in_line) - 1] == '\n') in_line[strlen (in_line) - 1] = (char) NULL; @@ -109,21 +113,23 @@ main (int argc, char *argv[]) if (error_code) { if (strncmp (in_line, "JobName=FAIL", 12) != 0) printf ("ERROR:"); - printf ("for job: %s\n", in_line, node_list); - printf ("node_scheduler: error %d from job_allocate on line %d\n\n", + printf ("for job: %s\n", in_line); + printf ("node_scheduler: error %d from job_allocate on line %d\n", error_code, line_num); } else { if (strncmp (in_line, "JobName=FAIL", 12) == 0) printf ("ERROR: "); - printf ("for job: %s\n nodes selected %s\n\n", + printf ("for job: %s\n nodes selected %s\n", in_line, node_list); if (job_id) xfree (job_id); if (node_list) xfree (node_list); - } - } + } + printf("time = %ld usec\n\n", (long) (clock() - start_time)); + } + exit (0); } #endif @@ -141,7 +147,7 @@ allocate_nodes (unsigned *bitmap) for (i = 0; i < node_record_count; i++) { if (bit_test (bitmap, i) == 0) continue; - node_record_table_ptr[i].node_state = STATE_STAGE_IN; + node_record_table_ptr[i].node_state = STATE_BUSY; bit_clear (idle_node_bitmap, i); } return; @@ -285,8 +291,8 @@ match_group (char *allow_groups, char *user_groups) /* - * pick_best_quadrics - identify the nodes which best fit the req_nodes and req_cpus counts - * for a system with Quadrics elan interconnect. + * pick_best_quadrics - identify the nodes which best fit the req_nodes and + * req_cpus counts for a system with Quadrics elan interconnect. * "best" is defined as either single set of consecutive nodes satisfying * the request and leaving the minimum number of unused nodes OR * the fewest number of consecutive node sets @@ -296,7 +302,8 @@ match_group (char *allow_groups, char *user_groups) * req_nodes - number of nodes required * req_cpus - number of cpus required * consecutive - nodes must be consecutive is 1, otherwise 0 - * output: bitmap - nodes not required to satisfy the request are cleared, other left set + * output: bitmap - nodes not required to satisfy the request are cleared, + * other left set * returns zero on success, EINVAL otherwise * globals: node_record_count - count of nodes configured * node_record_table_ptr - pointer to global node table @@ -314,8 +321,8 @@ pick_best_quadrics (bitstr_t *bitmap, bitstr_t *req_bitmap, int req_nodes, int *consec_req; /* are nodes from this set required (in req_bitmap) */ int consec_index, consec_size; int rem_cpus, rem_nodes; /* remaining resources required */ - int best_fit_nodes, best_fit_cpus, best_fit_req, best_fit_location, - best_fit_sufficient; + int best_fit_nodes, best_fit_cpus, best_fit_req; + int best_fit_location = 0, best_fit_sufficient; if (bitmap == NULL) fatal ("pick_best_quadrics: bitmap pointer is NULL\n"); @@ -339,10 +346,11 @@ pick_best_quadrics (bitstr_t *bitmap, bitstr_t *req_bitmap, int req_nodes, consec_start[consec_index] = index; i = node_record_table_ptr[index].cpus; if (req_bitmap && bit_test (req_bitmap, index)) { - if (consec_req[consec_index] == -1) /* first required node in set */ + if (consec_req[consec_index] == -1) + /* first required node in set */ consec_req[consec_index] = index; - rem_cpus -= i; /* reduce count of additional resources required */ - rem_nodes--; /* reduce count of additional resources required */ + rem_cpus -= i; + rem_nodes--; } else { bit_clear (bitmap, index); @@ -351,7 +359,8 @@ pick_best_quadrics (bitstr_t *bitmap, bitstr_t *req_bitmap, int req_nodes, } } else if (consec_nodes[consec_index] == 0) { - consec_req[consec_index] = -1; /* already picked up any required nodes */ + consec_req[consec_index] = -1; + /* already picked up any required nodes */ /* re-use this record */ } else { @@ -455,7 +464,6 @@ pick_best_quadrics (bitstr_t *bitmap, bitstr_t *req_bitmap, int req_nodes, consec_nodes[best_fit_location] = 0; } - cleanup: if (consec_cpus) xfree (consec_cpus); if (consec_nodes) @@ -480,7 +488,8 @@ pick_best_quadrics (bitstr_t *bitmap, bitstr_t *req_bitmap, int req_nodes, * req_nodes - count of nodes required by the job * contiguous - set to 1 if allocated nodes must be contiguous, 0 otherwise * shared - set to 1 if nodes may be shared, 0 otherwise - * max_nodes - maximum number of nodes permitted for job, -1 for none (partition limit) + * max_nodes - maximum number of nodes permitted for job, + * INFIITE for no limit (partition limit) * output: req_bitmap - pointer to bitmap of selected nodes * returns 0 on success, EAGAIN if request can not be satisfied now, * EINVAL if request can never be satisfied (insufficient contiguous nodes) @@ -488,22 +497,21 @@ pick_best_quadrics (bitstr_t *bitmap, bitstr_t *req_bitmap, int req_nodes, */ int pick_best_nodes (struct node_set *node_set_ptr, int node_set_size, - bitstr_t **req_bitmap, int req_cpus, int req_nodes, - int contiguous, int shared, int max_nodes) + bitstr_t **req_bitmap, uint32_t req_cpus, uint32_t req_nodes, + int contiguous, int shared, uint32_t max_nodes) { - int error_code, i, j, pick_code, size; + int error_code, i, j, pick_code; int total_nodes, total_cpus; /* total resources configured in partition */ int avail_nodes, avail_cpus; /* resources available for use now */ bitstr_t *avail_bitmap, *total_bitmap; int max_feature, min_feature; - int *cpus_per_node; int avail_set, total_set, runable; if (node_set_size == 0) { info ("pick_best_nodes: empty node set for selection"); return EINVAL; } - if ((max_nodes != -1) && (req_nodes > max_nodes)) { + if ((max_nodes != INFINITE) && (req_nodes > max_nodes)) { info ("pick_best_nodes: more nodes required than possible in partition"); return EINVAL; } @@ -542,7 +550,7 @@ pick_best_nodes (struct node_set *node_set_ptr, int node_set_size, min_feature = node_set_ptr[i].feature; } - runable = 0; /* assume not runable until otherwise demonstrated */ + runable = 0; /* assume not runable until otherwise demonstrated */ for (j = min_feature; j <= max_feature; j++) { avail_set = total_set = 0; for (i = 0; i < node_set_size; i++) { @@ -593,9 +601,10 @@ pick_best_nodes (struct node_set *node_set_ptr, int node_set_size, pick_best_quadrics (avail_bitmap, req_bitmap[0], req_nodes, req_cpus, contiguous); - if ((pick_code == 0) && (max_nodes != -1) + if ((pick_code == 0) && (max_nodes != INFINITE) && (bit_set_count (avail_bitmap) > max_nodes)) { - info ("pick_best_nodes: too many nodes selected"); + info ("pick_best_nodes: too many nodes selected %u of %u", + bit_set_count (avail_bitmap), max_nodes); error_code = EINVAL; break; } @@ -612,17 +621,18 @@ pick_best_nodes (struct node_set *node_set_ptr, int node_set_size, (total_nodes > req_nodes) && (total_cpus > req_cpus) && ((req_bitmap[0] == NULL) || (bit_super_set (req_bitmap[0], total_bitmap) == 1)) - && ((max_nodes == -1) || (req_nodes <= max_nodes))) { + && ((max_nodes == INFINITE) || (req_nodes <= max_nodes))) { /* determine if job could possibly run */ /* (if configured nodes all available) */ pick_code = pick_best_quadrics (total_bitmap, req_bitmap[0], req_nodes, req_cpus, contiguous); - if ((pick_code == 0) && (max_nodes != -1) - && (bit_set_count (avail_bitmap) > max_nodes)) { + if ((pick_code == 0) && (max_nodes != INFINITE) + && (bit_set_count (total_bitmap) > max_nodes)) { error_code = EINVAL; - info ("pick_best_nodes: too many nodes selected"); + info ("pick_best_nodes: %u nodes selected, max is %u", + bit_set_count (avail_bitmap), max_nodes); } if (pick_code == 0) runable = 1; @@ -659,12 +669,13 @@ pick_best_nodes (struct node_set *node_set_ptr, int node_set_size, int select_nodes (struct job_record *job_ptr) { - int error_code, i, node_set_index, node_set_size; + int error_code, i, node_set_index, node_set_size = 0; bitstr_t *req_bitmap, *scratch_bitmap; - ListIterator config_record_iterator; /* for iterating through config_list */ + ListIterator config_record_iterator; struct config_record *config_record_point; struct node_set *node_set_ptr; struct part_record *part_ptr; + int tmp_feature, check_node_config; req_bitmap = scratch_bitmap = NULL; config_record_iterator = (ListIterator) NULL; @@ -695,9 +706,8 @@ select_nodes (struct job_record *job_ptr) if (config_record_iterator == NULL) fatal ("select_nodes: ListIterator_create unable to allocate memory"); - while (config_record_point = - (struct config_record *) list_next (config_record_iterator)) { - int tmp_feature, check_node_config; + while ((config_record_point = + (struct config_record *) list_next (config_record_iterator))) { tmp_feature = valid_features (job_ptr->details->features, config_record_point->feature); @@ -819,8 +829,7 @@ select_nodes (struct job_record *job_ptr) error ("bitmap2node_name error %d", error_code); goto cleanup; } - build_node_list (req_bitmap, job_ptr->details->dist, - job_ptr->details->procs_per_task, + build_node_list (req_bitmap, &job_ptr->details->node_list, &job_ptr->details->total_procs); allocate_nodes (req_bitmap); @@ -847,7 +856,8 @@ select_nodes (struct job_record *job_ptr) } -/* valid_features - determine if the requested features are satisfied by those available +/* + * valid_features - determine if the requested features are satisfied by those available * input: requested - requested features (by a job) * available - available features (on a node) * output: returns 0 if request is not satisfied, otherwise an integer indicating @@ -862,7 +872,7 @@ valid_features (char *requested, char *available) char *tmp_requested, *str_ptr1; int bracket, found, i, option, position, result; int last_op; /* last operation 0 for or, 1 for and */ - int save_op, save_result; /* for bracket support */ + int save_op = 0, save_result = 0; /* for bracket support */ if (requested == NULL) return 1; /* no constraints */ diff --git a/src/slurmctld/partition_mgr.c b/src/slurmctld/partition_mgr.c index 71ff1e151b5c2ed46dd2e5fa2f4317c1f93bad39..ac95c380cf8557e93fd5b1c4c5dedbc337589c98 100644 --- a/src/slurmctld/partition_mgr.c +++ b/src/slurmctld/partition_mgr.c @@ -9,6 +9,7 @@ # include <config.h> #endif +#include <ctype.h> #include <errno.h> #include <stdio.h> #include <stdlib.h> @@ -33,6 +34,7 @@ int list_find_part (void *part_entry, void *key); #if DEBUG_MODULE /* main is used here for module testing purposes only */ +int main (int argc, char *argv[]) { int error_code, i; @@ -40,18 +42,6 @@ main (int argc, char *argv[]) struct part_record *part_ptr; char *dump; int dump_size; - char req_name[MAX_NAME_LEN]; /* name of the partition */ - char next_name[MAX_NAME_LEN]; /* name of the next partition */ - int max_time; /* -1 if unlimited */ - int max_nodes; /* -1 if unlimited */ - int total_nodes; /* total number of nodes in the partition */ - int total_cpus; /* total number of cpus in the partition */ - char *nodes; /* names of nodes in partition */ - char *allow_groups; /* NULL indicates all */ - int key; /* 1 if slurm distributed key is required for use of partition */ - int state_up; /* 1 if state is up */ - int shared; /* 1 if partition can be shared */ - bitstr_t *node_bitmap; /* bitmap of nodes in partition */ char update_spec[] = "MaxTime=34 MaxNodes=56 Key=NO State=DOWN Shared=FORCE"; log_options_t opts = LOG_OPTS_STDERR_ONLY; @@ -316,7 +306,7 @@ dump_all_part (char **buffer_ptr, int *buffer_size, time_t * update_time) ListIterator part_record_iterator; /* for iterating through part_record list */ struct part_record *part_record_point; /* pointer to part_record */ char *buffer; - int buffer_offset, buffer_allocated, error_code, i, record_size; + int buffer_offset, buffer_allocated, error_code; char out_line[BUF_SIZE]; buffer_ptr[0] = NULL; @@ -337,8 +327,8 @@ dump_all_part (char **buffer_ptr, int *buffer_size, time_t * update_time) goto cleanup; /* write individual partition records */ - while (part_record_point = - (struct part_record *) list_next (part_record_iterator)) { + while ((part_record_point = + (struct part_record *) list_next (part_record_iterator))) { if (part_record_point->magic != PART_MAGIC) fatal ("dump_all_part: data integrity is bad"); @@ -460,8 +450,8 @@ int init_part_conf () strcpy (default_part.name, "DEFAULT"); default_part.allow_groups = (char *) NULL; - default_part.max_time = -1; - default_part.max_nodes = -1; + default_part.max_time = INFINITE; + default_part.max_nodes = INFINITE; default_part.key = 0; default_part.state_up = 1; default_part.shared = 0; @@ -692,13 +682,19 @@ update_part (char *partition_name, char *spec) if (max_time_val != NO_VAL) { info ("update_part: setting max_time to %d for partition %s", max_time_val, partition_name); - part_ptr->max_time = max_time_val; + if (max_time_val == -1) + part_ptr->max_time = INFINITE; + else + part_ptr->max_time = max_time_val; } if (max_nodes_val != NO_VAL) { info ("update_part: setting max_nodes to %d for partition %s", max_nodes_val, partition_name); - part_ptr->max_nodes = max_nodes_val; + if (max_nodes_val == -1) + part_ptr->max_nodes = INFINITE; + else + part_ptr->max_nodes = max_nodes_val; } if (key_val != NO_VAL) { diff --git a/src/slurmctld/read_config.c b/src/slurmctld/read_config.c index f58fa28ddcc6da75ba69619479e13428c059c068..fbb4c0de700d838f9137f694c8053a6d11e98711 100644 --- a/src/slurmctld/read_config.c +++ b/src/slurmctld/read_config.c @@ -18,6 +18,7 @@ #include <stdio.h> #include <string.h> #include <syslog.h> +#include <unistd.h> #include "slurm.h" #include "list.h" @@ -32,10 +33,10 @@ char *control_machine = NULL; #if DEBUG_MODULE /* main is used here for module testing purposes only */ +int main (int argc, char *argv[]) { - int error_code, start_inx, end_inx, count_inx; - char out_line[BUF_SIZE]; - char *format, *node_name, bitmap[128]; + int error_code; + char bitmap[128]; char *partitions[] = { "login", "debug", "batch", "class", "end" }; struct part_record *part_ptr; int cycles, i, found; @@ -189,8 +190,8 @@ build_bitmaps () { if (config_record_iterator == NULL) fatal ("build_bitmaps: list_iterator_create unable to allocate memory"); - while (config_record_point = - (struct config_record *) list_next (config_record_iterator)) { + while ((config_record_point = + (struct config_record *) list_next (config_record_iterator))) { if (config_record_point->node_bitmap) bit_free (config_record_point->node_bitmap); @@ -220,7 +221,8 @@ build_bitmaps () { if (part_record_iterator == NULL) fatal ("build_bitmaps: list_iterator_create unable to allocate memory"); - while (part_record_point = (struct part_record *) list_next (part_record_iterator)) { + while ((part_record_point = + (struct part_record *) list_next (part_record_iterator))) { if (part_record_point->node_bitmap) bit_free (part_record_point->node_bitmap); part_record_point->node_bitmap = (bitstr_t *) bit_alloc (node_record_count); @@ -287,13 +289,13 @@ init_slurm_conf () { backup_controller = NULL; } - if (error_code = init_node_conf ()) + if ((error_code = init_node_conf ())) return error_code; - if (error_code = init_part_conf ()) + if ((error_code = init_part_conf ())) return error_code; - if (error_code = init_job_conf ()) + if ((error_code = init_job_conf ())) return error_code; return 0; @@ -315,12 +317,12 @@ parse_node_spec (char *in_line) { int error_code, i, node_count; int state_val, cpus_val, real_memory_val, tmp_disk_val, weight_val; struct node_record *node_record_point; - struct config_record *config_point; + struct config_record *config_point = NULL; node_name = state = feature = node_list = (char *) NULL; cpus_val = real_memory_val = state_val = NO_VAL; tmp_disk_val = weight_val = NO_VAL; - if (error_code = load_string (&node_name, "NodeName=", in_line)) + if ((error_code = load_string (&node_name, "NodeName=", in_line))) return error_code; if (node_name == NULL) return 0; /* no node info */ @@ -441,12 +443,11 @@ parse_node_spec (char *in_line) { */ int parse_part_spec (char *in_line) { - int line_num; /* line number in input file */ char *allow_groups, *nodes, *partition_name; char *default_str, *key_str, *shared_str, *state_str; - int max_time_val, max_nodes_val, key_val, default_val, state_val, - shared_val; - int error_code, i; + int max_time_val, max_nodes_val, key_val, default_val; + int state_val, shared_val; + int error_code; struct part_record *part_record_point; partition_name = (char *) NULL; @@ -454,8 +455,8 @@ parse_part_spec (char *in_line) { max_time_val = max_nodes_val = key_val = default_val = state_val = shared_val = NO_VAL; - if (error_code = - load_string (&partition_name, "PartitionName=", in_line)) + if ((error_code = + load_string (&partition_name, "PartitionName=", in_line))) return error_code; if (partition_name == NULL) return 0; /* no partition info */ @@ -641,8 +642,6 @@ read_slurm_conf (char *file_name) { FILE *slurm_spec_file; /* pointer to input data file */ int line_num; /* line number in input file */ char in_line[BUF_SIZE]; /* input line */ - char scratch[BUF_SIZE]; /* scratch area for parsing the input line */ - char *str_ptr1, *str_ptr2, *str_ptr3; int i, j, error_code; /* initialization */ @@ -695,13 +694,13 @@ read_slurm_conf (char *file_name) { } /* node configuration parameters */ - if (error_code = parse_node_spec (in_line)) { + if ((error_code = parse_node_spec (in_line))) { fclose (slurm_spec_file); return error_code; } /* partition configuration parameters */ - if (error_code = parse_part_spec (in_line)) { + if ((error_code = parse_part_spec (in_line))) { fclose (slurm_spec_file); return error_code; } @@ -725,7 +724,7 @@ read_slurm_conf (char *file_name) { return EINVAL; } rehash (); - if (error_code = build_bitmaps ()) + if ((error_code = build_bitmaps ())) return error_code; list_sort (config_list, &list_compare_config);