diff --git a/NEWS b/NEWS index 5fb6752e1f48cc272cc172f5e45fa808c480e2a5..259ce99919bddc46e723d0f6ad66651982155d57 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,7 @@ documents those changes that are of interest to users and admins. * Changes in SLURM 1.2.0-pre6 ============================= + -- Maintain actually job step run time with suspend/resume use. * Changes in SLURM 1.2.0-pre5 ============================= diff --git a/slurm/slurm.h.in b/slurm/slurm.h.in index d3599f1bed426573ed005e0b0926a91b41282e7f..084e6f683fa0f4c9f6db461fdd89545b530617cc 100644 --- a/slurm/slurm.h.in +++ b/slurm/slurm.h.in @@ -680,6 +680,7 @@ typedef struct { uint32_t user_id; /* user the job runs as */ uint32_t num_tasks; /* number of tasks */ time_t start_time; /* step start time */ + time_t run_time; /* net run time (factor out time suspended) */ char *partition; /* name of assigned partition */ char *nodes; /* list of nodes allocated to job_step */ char *name; /* name of job step */ diff --git a/src/common/slurm_protocol_pack.c b/src/common/slurm_protocol_pack.c index ab468ed553ce28e375ce94f423924add7f293bb4..8f7dad2950cb761b8d28bf76e2448e69ca8f265e 100644 --- a/src/common/slurm_protocol_pack.c +++ b/src/common/slurm_protocol_pack.c @@ -1827,6 +1827,7 @@ _unpack_job_step_info_members(job_step_info_t * step, Buf buffer) safe_unpack32(&step->num_tasks, buffer); safe_unpack_time(&step->start_time, buffer); + safe_unpack_time(&step->run_time, buffer); safe_unpackstr_xmalloc(&step->partition, &uint16_tmp, buffer); safe_unpackstr_xmalloc(&step->nodes, &uint16_tmp, buffer); safe_unpackstr_xmalloc(&step->name, &uint16_tmp, buffer); diff --git a/src/slurmctld/job_mgr.c b/src/slurmctld/job_mgr.c index 4624d5f799523084b9a5d0347ac6718723b5879b..f682a4c137998af181be1f4436ac024e6dee6c60 100644 --- a/src/slurmctld/job_mgr.c +++ b/src/slurmctld/job_mgr.c @@ -943,6 +943,7 @@ static void _dump_job_step_state(struct step_record *step_ptr, Buf buffer) } pack_time(step_ptr->start_time, buffer); + pack_time(step_ptr->pre_sus_time, buffer); packstr(step_ptr->host, buffer); packstr(step_ptr->name, buffer); packstr(step_ptr->network, buffer); @@ -960,7 +961,7 @@ static int _load_step_state(struct job_record *job_ptr, Buf buffer) struct step_record *step_ptr = NULL; uint16_t step_id, cyclic_alloc, name_len, port, batch_step, bit_cnt; uint32_t exit_code; - time_t start_time; + time_t start_time, pre_sus_time; char *host = NULL; char *name = NULL, *network = NULL, *bit_fmt = NULL; switch_jobinfo_t switch_tmp = NULL; @@ -977,6 +978,7 @@ static int _load_step_state(struct job_record *job_ptr, Buf buffer) } safe_unpack_time(&start_time, buffer); + safe_unpack_time(&pre_sus_time, buffer); safe_unpackstr_xmalloc(&host, &name_len, buffer); safe_unpackstr_xmalloc(&name, &name_len, buffer); safe_unpackstr_xmalloc(&network, &name_len, buffer); @@ -1015,6 +1017,7 @@ static int _load_step_state(struct job_record *job_ptr, Buf buffer) step_ptr->batch_step = batch_step; host = NULL; /* re-used, nothing left to free */ step_ptr->start_time = start_time; + step_ptr->pre_sus_time = pre_sus_time; slurm_step_layout_destroy(step_ptr->step_layout); step_ptr->step_layout = step_layout; @@ -4479,6 +4482,7 @@ extern int job_suspend(suspend_msg_t *sus_ptr, uid_t uid, difftime(now, job_ptr->start_time); } + suspend_job_step(job_ptr); } else if (sus_ptr->op == RESUME_JOB) { if (job_ptr->job_state != JOB_SUSPENDED) { rc = ESLURM_DISABLED; diff --git a/src/slurmctld/slurmctld.h b/src/slurmctld/slurmctld.h index 0bb3399292cea65ef81c7c60b2bdf343e07971b0..17b0e3deebdfd271a0805446d4445f7ecd0e585e 100644 --- a/src/slurmctld/slurmctld.h +++ b/src/slurmctld/slurmctld.h @@ -391,6 +391,10 @@ struct step_record { uint16_t cyclic_alloc; /* set for cyclic task allocation across nodes */ time_t start_time; /* step allocation time */ +/* time_t suspend_time; * time step last suspended or resumed + * implicitly the same as suspend_time + * in the job record */ + time_t pre_sus_time; /* time step ran prior to last suspend */ bitstr_t *step_node_bitmap; /* bitmap of nodes allocated to job step */ uint16_t port; /* port for srun communications */ @@ -1256,6 +1260,9 @@ extern bool step_on_node(struct job_record *job_ptr, extern int step_partial_comp(step_complete_msg_t *req, int *rem, int *max_rc); +/* Update time stamps for job step suspend */ +extern void suspend_job_step(struct job_record *job_ptr); + /* * Synchronize the batch job in the system with their files. * All pending batch jobs must have script and environment files diff --git a/src/slurmctld/step_mgr.c b/src/slurmctld/step_mgr.c index 9275a1580a83fc5de10da22c1bf8ad15139e7db6..e6fc8ecddb4de9e1a834a0958064f82e5bb7e525 100644 --- a/src/slurmctld/step_mgr.c +++ b/src/slurmctld/step_mgr.c @@ -845,29 +845,39 @@ extern slurm_step_layout_t *step_layout_create(struct step_record *step_ptr, * IN step - pointer to a job step record * IN/OUT buffer - location to store data, pointers automatically advanced */ -static void _pack_ctld_job_step_info(struct step_record *step, Buf buffer) +static void _pack_ctld_job_step_info(struct step_record *step_ptr, Buf buffer) { int task_cnt; char *node_list = NULL; + time_t begin_time, run_time; - if(step->step_layout) { - task_cnt = step->step_layout->task_cnt; - node_list = step->step_layout->node_list; + if (step_ptr->step_layout) { + task_cnt = step_ptr->step_layout->task_cnt; + node_list = step_ptr->step_layout->node_list; } else { - task_cnt = step->job_ptr->num_procs; - node_list = step->job_ptr->nodes; + task_cnt = step_ptr->job_ptr->num_procs; + node_list = step_ptr->job_ptr->nodes; } - pack32((uint32_t)step->job_ptr->job_id, buffer); - pack16((uint16_t)step->step_id, buffer); - pack32((uint32_t)step->job_ptr->user_id, buffer); + pack32((uint32_t)step_ptr->job_ptr->job_id, buffer); + pack16((uint16_t)step_ptr->step_id, buffer); + pack32((uint32_t)step_ptr->job_ptr->user_id, buffer); pack32((uint32_t)task_cnt, buffer); - pack_time(step->start_time, buffer); - packstr(step->job_ptr->partition, buffer); + pack_time(step_ptr->start_time, buffer); + if (step_ptr->job_ptr->job_state == JOB_SUSPENDED) { + run_time = step_ptr->pre_sus_time; + } else { + begin_time = MAX(step_ptr->start_time, + step_ptr->job_ptr->suspend_time); + run_time = step_ptr->pre_sus_time + + difftime(time(NULL), begin_time); + } + pack_time(run_time, buffer); + packstr(step_ptr->job_ptr->partition, buffer); packstr(node_list, buffer); - packstr(step->name, buffer); - packstr(step->network, buffer); - pack_bit_fmt(step->step_node_bitmap, buffer); + packstr(step_ptr->name, buffer); + packstr(step_ptr->network, buffer); + pack_bit_fmt(step_ptr->step_node_bitmap, buffer); } @@ -1332,3 +1342,35 @@ extern int step_epilog_complete(struct job_record *job_ptr, return rc; } +static void +_suspend_job_step(struct job_record *job_ptr, + struct step_record *step_ptr, time_t now) +{ + if ((job_ptr->suspend_time) + && (job_ptr->suspend_time > step_ptr->start_time)) { + step_ptr->pre_sus_time += + difftime(now, + job_ptr->suspend_time); + } else { + step_ptr->pre_sus_time += + difftime(now, + step_ptr->start_time); + } + +} + +/* Update time stamps for job step suspend */ +extern void +suspend_job_step(struct job_record *job_ptr) +{ + time_t now = time(NULL); + ListIterator step_iterator; + struct step_record *step_ptr; + + step_iterator = list_iterator_create (job_ptr->step_list); + while ((step_ptr = (struct step_record *) list_next (step_iterator))) { + _suspend_job_step(job_ptr, step_ptr, now); + } + list_iterator_destroy (step_iterator); +} + diff --git a/src/squeue/print.c b/src/squeue/print.c index 76cedac0352c443914a1ffe2d2548e72ba3352d7..3ed0857d8a86e7e1192156ff05c1f9c0eec97420 100644 --- a/src/squeue/print.c +++ b/src/squeue/print.c @@ -1158,7 +1158,7 @@ int _print_step_time_used(job_step_info_t * step, int width, bool right, if (step == NULL) /* Print the Header instead */ _print_str("TIME", width, right, true); else { - long delta_t = difftime(time(NULL), step->start_time); + long delta_t = step->run_time; _print_secs(delta_t, width, right, false); } if (suffix)