From 924ac32c1dca77e74362ec8b2608cd8db843811c Mon Sep 17 00:00:00 2001 From: Rongsong Shen Date: Mon, 7 Sep 2026 15:30:56 +0000 Subject: [PATCH] fix(scheduler): global limits on per-host resources now read the correct want (bug-1789) sched_fill_limit_requests() used to read a limit's underlying resource's want from the same vector its own virtual-resource entry gets written to. That's wrong whenever the two differ in scope -- e.g. a GLOBAL limit built on top of a per-host resource like "slots" (limits.yaml's ug1_normal_slots): the limit's own vres entry belongs in alloc_req->shared, but "slots"'s want is only ever staged into alloc_req->host by seqjob/parjob_prepare_allocation(), so the old code always read a zero and silently never enforced the cap. Now both the read source and write destination are derived independently from each resource's own XCE_RESF_GLOBAL flag (vres->res for the source, vres->vres for the destination) -- the same flag calc_wanted_global_resvals()/calc_wanted_host_resvals() (resreq.c) already dispatch on, so this is the existing rule applied consistently rather than a new one. Also drops sched_fill_limit_requests()'s unused xce_scheduler_t* parameter. Full scheduler suite: 76/77 (the one failure, test_job_rusage_reconciles_ mem_reservation_against_usage, is bug-1762, pre-existing and unrelated). Live-verified against a fresh single-node deploy. Filed bug-1790 to track a known, deliberately out-of-scope residual gap: a future global limit on a per-host resource other than "slots" would need calc_wanted_host_resvals() to also run during the global phase for that resource, which nothing currently does. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01GLfB5uWRdmx2WiZSFC7Fm7 --- .wolf/buglog.json | 34 ++- src/scheduler/include/scheduler.h | 2 +- src/scheduler/src/plugin.c | 5 +- src/scheduler/src/resource.c | 41 +++- .../testsuite/test_driver_session_ordering.c | 5 +- .../test_maxtasks_wiring_sim_driver_parity.c | 5 +- src/scheduler/testsuite/test_picker_wiring.c | 5 +- .../test_plugin_picker_registration.c | 5 +- .../testsuite/test_record_lifecycle.c | 5 +- .../test_repl_breakpoints_inspection.c | 5 +- .../testsuite/test_repl_equivalence.c | 5 +- .../testsuite/test_repl_event_echo.c | 5 +- .../testsuite/test_repl_execution_control.c | 5 +- src/scheduler/testsuite/test_repl_help.c | 5 +- .../testsuite/test_repl_prompt_context.c | 5 +- .../testsuite/test_repl_resource_table.c | 5 +- .../testsuite/test_repl_round_rollup.c | 5 +- .../testsuite/test_repl_snapshot_params.c | 5 +- .../testsuite/test_repl_step_verbosity.c | 5 +- .../testsuite/test_resource_accounting.c | 219 ++++++++++++++++++ src/scheduler/testsuite/test_sim_alt_events.c | 5 +- .../testsuite/test_sim_equivalence.c | 5 +- src/scheduler/testsuite/test_sim_event_loop.c | 5 +- .../testsuite/test_sim_print_decision_gate.c | 5 +- .../testsuite/test_sim_record_output.c | 5 +- .../testsuite/test_sim_session_ordering.c | 5 +- .../test_sim_snapshot_reconcile_gap.c | 5 +- src/scheduler/testsuite/test_sim_verify.c | 5 +- 28 files changed, 332 insertions(+), 84 deletions(-) diff --git a/.wolf/buglog.json b/.wolf/buglog.json index 625131d5..46899fab 100644 --- a/.wolf/buglog.json +++ b/.wolf/buglog.json @@ -21410,25 +21410,47 @@ "error_message": "After bug-1784 through bug-1788 all fixed and live-verified (all 7 limits in limits.yaml now correctly match and instantiate usage tracking for every job), the actual numeric cap still does not reject anyone: 10 single-slot jobs submitted as user1 on queue normal against ug1_normal_slots's configured value:8 cap all still reach RUN, none PEND.", "file": "src/scheduler/src/resource.c (sched_fill_limit_requests)", "root_cause": "NOT YET ROOT-CAUSED TO A FIX -- traced to a specific, likely-defective computation, but the correct intended semantics were not established this session (deliberately stopped here rather than guess at production logic). Chain traced and CONFIRMED CORRECT up to one point: match_job_global_limit_ populates obj->glimits (fixed, bug-1784-1788) -> plugin.c's plugin_prepare_allocation calls sched_fill_limit_requests(sched, &(ctx->alloc_req.shared), &(obj->glimits)) when ctx->worker==NULL (the global/non-host-scoped case, correct for ug1_normal_slots) -> seqjob_allocator.c/parjob_allocator.c both correctly call sched_check_shared_satisfy(sched, uncomit, &(ctx->alloc_req.shared), &(ctx->unmeet)) and correctly reject (PREASON_NO_RESOURCE, rc=0) when a shared resource's wanted amount would exceed its tracked total (itself correctly set to limit->val.val=8 by update_limit_res_value(), which DOES run correctly now). The break is inside sched_fill_limit_requests() itself (resource.c:912-931): for each matched limit, it computes the job's \"wanted\" quantity of the limit's virtual resource via `val = get_resval_by_id(vec, vres->res->idx)` where `vec` is `ctx->alloc_req.shared` ITSELF -- i.e. it looks up how many units of the limit's UNDERLYING resource (e.g. \"slots\") the job already requests, inside the SAME shared-resource-request vector it is about to write the limit's own synthetic entry into. But \"slots\" is inherently a per-host resource, requested via ctx->alloc_req.HOST (task/slot count per host), not ctx->alloc_req.shared -- so this lookup always misses, get_resval_by_id's own not-found fallback returns 0.0, and every job is recorded as requesting ZERO units of ug1_normal_slots regardless of how many slots it actually asks for. sched_check_shared_satisfy then trivially \"satisfies\" a wanted=0 request against any total, no matter how many jobs are already running -- the cap can never bind. NOT CONFIRMED whether this is a straightforward bug (should read from ctx->alloc_req.host or from resreq directly) or reflects a genuine, unaddressed design gap in how a GLOBAL (non-host-scoped) limit is meant to interact with a per-host-scoped underlying resource like slots -- the fix requires understanding what \"consumption count\" SHOULD mean for this combination, not just correcting an obvious return-code mistake like bug-1784-1788 all were.", - "fix": "NOT FIXED -- deliberately stopped here per explicit user instruction (\"land what's confirmed\") rather than guess at the intended design of cross-scope limit resource consumption. This is a 6th, architecturally distinct issue from the bug-1784-1788 cascade (which were all clear-cut, single-fix logic errors); this one needs either a design decision (what should a slots-resname'd global limit's per-job consumption be computed from?) or deeper investigation into whether an existing, unexamined mechanism already threads the job's task/slot count into a form sched_fill_limit_requests can read. NEXT STEPS for a follow-up session: (1) check whether ctx->alloc_req.host already carries a per-job \"slots wanted\" entry at the point plugin_prepare_allocation's ctx->worker==NULL branch runs (it may not yet, if host selection hasn't happened) -- if the global-limit-evaluation phase genuinely precedes host selection, the job's own resreq/mintasks (not a per-host allocation) is likely the correct source instead; (2) check test_scheduler_backpressure.c / any existing shared-resource-limit test fixture for a working end-to-end precedent that might already demonstrate correct semantics for a DIFFERENT (non-slots) global limit; (3) consider whether this NEEDS fixing at all for the ORIGINAL gitea#46 report, given the reporter's dispatch-stops-at-8 was against raw host MAX_SLOT capacity (confirmed working correctly, unaffected by any of bug-1784-1789) rather than a usergroup limit -- the usergroup-limit cascade was discovered via this session's OWN verification attempt, not the original report.", + "fix": "FIXED (2026-09-07, follow-up session). Root-caused via codegraph trace of plugin_prepare_allocation()'s full hook loop (not just the two call sites the prior session had traced): seqjob_prepare_allocation()/parjob_prepare_allocation() (the allocator plugins' own prepare_allocation_hook) ALWAYS stage the job's wanted slot count into ctx->alloc_req.host -- even during the ctx->worker==NULL/global pass -- because \"slots\" is deliberately excluded from calc_wanted_global_resvals()/calc_wanted_host_resvals() (it's per-host, not XCE_RESF_GLOBAL) and is staged by a separate, unbranched follow-up store. This confirmed the prior session's NEXT-STEPS item (1): the job's real wanted slot count (ctx->nslots, set earlier in that SAME prepare_allocation call) is already available and correct for both phases -- 1/seqjob or primary->maxTasks/parjob-global or the current bucket's count/parjob-per-host -- it just was never read from the right place. FIRST ATTEMPT (reverted): tried mirroring the ctx->worker branch into the seqjob/parjob \"add slots\" store itself (writing into ctx->alloc_req.shared during the global phase) -- this broke 6 previously-passing tests (seqjob/parjob dispatch tests going from DISPATCH to PEND) because ctx->alloc_req.shared is also read by sched_check_shared_satisfy() against sched->core.sharedInst, the GLOBAL capacity pool, which never tracks \"slots\" (a per-host-only resource) -- injecting a spurious \"slots\" want there made EVERY job's general satisfy check fail, not just limit-scoped ones. REAL FIX: read-side only, confined to limit evaluation. sched_fill_limit_requests() (resource.c) now takes an added xce_sched_ctx_t* ctx parameter; when a matched limit's underlying resource is \"slots\" (by name, matching this codebase's existing convention of hardcoding \"slots\" by name in seqjob/parjob's own key_find() calls), it uses (float)ctx->nslots directly as the wanted quantity instead of the always-missing get_resval_by_id(vec, ...) lookup; every other resource keeps the original vec-lookup behavior unchanged. plugin.c's two call sites updated to pass ctx; scheduler.h's extern declaration updated; all 23 testsuite files providing a link-satisfying no-op stub for the old 3-arg signature mechanically updated to the new 4-arg one (added (void)ctx; each, zero behavior change). TDD: 2 new focused unit tests in test_resource_accounting.c (white-box #include of resource.c) -- test_fill_limit_requests_global_slots_limit_uses_ctx_nslots (builds a bare xce_vres_t{res=\"slots\", vres=\"limit=X\"}, ctx.nslots=6, empty vec, asserts the limit's own vres entry gets stored with val=6.0) and test_fill_limit_requests_non_slots_resource_reads_from_vec (same shape for a \"mem\"-resname'd limit, vec pre-staged with 3.0, ctx.nslots=99 deliberately mismatched, asserts the mem path is unaffected and still reads 3.0 from vec, not ctx->nslots). Full scheduler suite: 76/77 (only pre-existing, unrelated bug-1762 failure remains -- test_job_rusage_reconciles_mem_reservation_against_usage, mem-reservation subsystem, untouched by this change). LIVE-VERIFIED: fresh single-node deploy (localhost:19997), 10 single-slot jobs submitted as user1 (ug1 member) on queue normal. hosts.yaml's default host template has max_slot: -1 (unlimited), ruling out raw host capacity as a factor. Scheduler trace confirms match_job_global_limit_ matching ug1_slots/ug1_normal_slots/limit1 (all three global, slots-resname'd) for every job, and resource.c's unsatisfy_() now logging a REAL non-zero wanted value for the limit's virtual resource on every charge (previously always 0.0, per this bug's original root_cause) -- e.g. 'unsatisfy_ resource 35 total 3.000000 inuse 3.000000 uncomit 0.000000 wanted 1.000000' for limit1 (cap 3.0, matches every non-rshen user including user1) once its 3rd job committed, correctly PENDing the 4th and all subsequent jobs with a genuine shortfall. limit1 (cap 3, broader scope: all users except rshen) bound before ug1_normal_slots (cap 8, narrower: ug1+normal only) could, since both match user1 identically and limit1's cap is lower -- expected overlapping-limit interaction (flagged in an earlier session's own observation), not a gap in this fix; both run through the identical, now-fixed code path. REVISED (2026-09-07, same session, user feedback): the name-based `strcmp(vres->res->name, \"slots\")` special-case above was flagged as unreliable (correctly -- it silently fails to generalize to any future per-host resource that isn't literally named \"slots\"). Replaced with a flag-based dispatch: sched_fill_limit_requests() now takes xce_sched_alloc_req_t* alloc_req instead of xce_sched_ctx_t* ctx (nothing else from ctx was ever used), and for each matched limit reads its underlying resource's want from whichever of alloc_req->shared/alloc_req->host that resource's own XCE_RESF_GLOBAL flag indicates -- the SAME flag calc_wanted_global_resvals()/calc_wanted_host_resvals() (resreq.c) themselves already dispatch on to decide where THEY write a resource's want, so this is not a new rule, just the existing one applied consistently. plugin.c's two call sites, scheduler.h, and all 23 testsuite stubs updated accordingly (mechanical param rename). Replaced the 2 name-based unit tests with 3 flag-based ones in test_resource_accounting.c: test_fill_limit_requests_global_limit_on_host_resource_reads_host (bug-1789's actual case: a GLOBAL limit's own write target is alloc_req->shared, but its per-host underlying resource's want must be read from alloc_req->host), test_fill_limit_requests_host_limit_on_host_resource_reads_host (already-working sibling case, unaffected), and test_fill_limit_requests_host_limit_on_global_resource_reads_shared (the new symmetric case this refactor adds real coverage for: a HOST-scoped limit's write target is alloc_req->host, but a genuinely-XCE_RESF_GLOBAL-flagged underlying resource's want must be read from alloc_req->shared instead -- proves the dispatch is a real bidirectional rule, not a one-off special case). Full scheduler suite re-run: 76/77 (same pre-existing bug-1762 failure, no new failures). Live re-verified end to end with a fully fresh redeploy (not just a scheduler restart against old job state, to keep the signal clean): identical result to the first live verification, byte-identical scheduler trace line ('unsatisfy_ resource 35 total 3.000000 inuse 3.000000 uncomit 0.000000 wanted 1.000000'), confirming the refactor is behavior-preserving for the current config. KNOWN RESIDUAL GAP (explicitly out of scope, not silently solved): a hypothetical NEW global limit on some per-host resource OTHER than \"slots\" (e.g. an absolute-value global mem cap, as opposed to the existing percent-based host-scoped mem limits) would still hit an analogous bug -- calc_wanted_global_resvals() itself skips any non-XCE_RESF_GLOBAL-flagged resource entirely, so such a resource's want is never computed anywhere during the global phase; \"slots\" only works because seqjob/parjob_prepare_allocation() stage it via a separate, always-run step outside the normal rusages loop, which no other resource has. Fixing that would mean teaching calc_wanted_global_resvals() (or an equivalent) to also compute a non-global resource's want when a currently-matched limit needs it -- a materially larger change, not needed by any limit in the current limits.yaml (the two mem-based limits, night_mem_pct/limits2, are both host-scoped, unaffected either way) and deliberately not attempted here. FURTHER SIMPLIFIED (2026-09-07, same session, user request): sched_fill_limit_requests()'s 1st parameter (xce_scheduler_t* sched) was entirely unused in the function body (only alloc_req and limits are referenced) -- a leftover from an earlier signature shape, not flagged by the prior same-day refactor that removed the old vec parameter. Dropped it: signature is now sched_fill_limit_requests(xce_sched_alloc_req_t* alloc_req, xlist_t* limits). Updated scheduler.h's extern declaration, both call sites in plugin.c's plugin_prepare_allocation() (the sched local var stays -- still used elsewhere in that function for plugin iteration), all 23 link-satisfying testsuite stubs (mechanical Python replace, byte-identical body across all 23), and the 3 real call sites in test_resource_accounting.c (the local `sched` var in each test stays too -- still needed for xce_sched_core_init()/makeResource() resource setup, just no longer passed to this call). Full scheduler suite re-verified after this change: 76/77 (same pre-existing, unrelated bug-1762 failure, no new failures).", "tags": [ "scheduler", "limit-plugin", "resource-allocation", - "design-gap", - "not-fixed", "gitea-46", - "needs-design-decision" + "live-verified", + "fixed" ], "related_bugs": [ "bug-1784", "bug-1785", "bug-1786", "bug-1787", - "bug-1788" + "bug-1788", + "bug-1790" ], "occurrences": 1, - "last_seen": "2026-09-07T10:30:00Z" + "last_seen": "2026-09-07T00:00:00Z" + }, + { + "id": "bug-1790", + "timestamp": "2026-09-07T00:00:00Z", + "error_message": "OPEN, NOT A CRASH -- known residual gap explicitly carved out of bug-1789's fix, filed for its own tracking per user request. A hypothetical NEW global limit defined on a per-host resource OTHER than \"slots\" (e.g. a future absolute-value global mem cap, as opposed to the existing percent-based host-scoped mem limits in limits.yaml) would silently under-enforce the same way bug-1789's slots limits did, for a different reason than bug-1789's root cause.", + "file": "src/lib/resreq.c", + "root_cause": "bug-1789 fixed sched_fill_limit_requests()'s READ side: it now picks whichever of alloc_req->shared/alloc_req->host to read a limit's underlying resource's want from by checking that resource's own XCE_RESF_GLOBAL flag on vres->res (and separately picks the WRITE destination for the limit's own vres entry by checking vres->vres's flag) -- see resource.c:928-955. That fix only works because alloc_req->host already has SOME value for \"slots\" to read, staged by seqjob_prepare_allocation()/parjob_prepare_allocation() via a separate, unconditional step outside the normal rusages loop, in EVERY phase including the global one. No other per-host resource gets this special treatment. The general population path -- calc_wanted_global_resvals() (src/lib/resreq.c:734) and calc_wanted_host_resvals() (src/lib/resreq.c:793), both called from seqjob_allocator.c/parjob_allocator.c's prepare_allocation hooks -- each unconditionally skip any resource whose XCE_RESF_GLOBAL flag doesn't match their own phase (calc_wanted_global_resvals() line 763: `if ((r->flags & XCE_RESF_GLOBAL) == 0) continue;`; calc_wanted_host_resvals() line 822: `if ((r->flags & XCE_RESF_GLOBAL) != 0) continue;`), and only calc_wanted_global_resvals() runs during the ctx->worker==NULL global phase. So for any per-host resource other than \"slots\", alloc_req->host is simply never populated with a want during the global phase -- sched_fill_limit_requests()'s now-correct read-side dispatch would read a genuine zero from an empty vector, not a population bug on its own side, but the net effect (a global limit on a per-host resource never seeing a nonzero want) is the same silent under-enforcement bug-1789 fixed for slots.", + "fix": "NOT FIXED -- deliberately out of scope, no limit in the current limits.yaml needs it (the two mem-based limits, night_mem_pct/limits2, are both host-scoped, unaffected either way). Suggested direction (per user note, 2026-09-07): apply the SAME flag-based-dispatch pattern bug-1789 already established on the read side to the population/write side too -- i.e. during the global phase, also check each matched global limit's underlying resource's own XCE_RESF_GLOBAL flag (vres->res->flags, the same check sched_fill_limit_requests() already performs) and, for any resource that flag marks non-global, additionally invoke calc_wanted_host_resvals() (or an equivalent per-resource want computation) to populate alloc_req->host for it before sched_fill_limit_requests() reads it -- rather than relying on a resource-specific special case like slots's separate staging step. This is a materially larger change than bug-1789's (touches the allocator plugins' prepare_allocation hooks, not just resource.c) and should get its own TDD cycle if/when a real limit needs it.", + "tags": [ + "scheduler", + "resource-accounting", + "limits", + "global-limit", + "pre-existing", + "out-of-scope", + "severity-low" + ], + "related_bugs": [ + "bug-1789" + ], + "occurrences": 1, + "last_seen": "2026-09-07T00:00:00Z" } ] } diff --git a/src/scheduler/include/scheduler.h b/src/scheduler/include/scheduler.h index 57617ad3..36933f53 100644 --- a/src/scheduler/include/scheduler.h +++ b/src/scheduler/include/scheduler.h @@ -323,6 +323,6 @@ extern int sched_try_alloc_on_host_(xce_sched_worker_t*, extern int get_resvals(zarray_t*, int, int*, float*); extern int put_resvals(zarray_t*, int, int*, float*); extern request_res_t* make_resource_request(char*, float); -extern int sched_fill_limit_requests(xce_scheduler_t*, xvec_idval_t*, xlist_t*); +extern int sched_fill_limit_requests(xce_sched_alloc_req_t*, xlist_t*); #endif diff --git a/src/scheduler/src/plugin.c b/src/scheduler/src/plugin.c index b5c06f27..fc1ef4b6 100644 --- a/src/scheduler/src/plugin.c +++ b/src/scheduler/src/plugin.c @@ -644,8 +644,7 @@ int plugin_prepare_allocation(void* arg, xce_sched_ctx_t* ctx) if (ctx->worker == NULL) { /* sequence/parallel job plugin should fill the basic rusages based on * resreq */ - sched_fill_limit_requests(sched, &(ctx->alloc_req.shared), - &(obj->glimits)); + sched_fill_limit_requests(&(ctx->alloc_req), &(obj->glimits)); } else { xlist_t* hlimits = NULL; @@ -653,7 +652,7 @@ int plugin_prepare_allocation(void* arg, xce_sched_ctx_t* ctx) * resreq */ hlimits = (xlist_t*)zarray_get(&(obj->hlimits), ctx->worker->idx); if (hlimits != NULL) { - sched_fill_limit_requests(sched, &(ctx->alloc_req.host), hlimits); + sched_fill_limit_requests(&(ctx->alloc_req), hlimits); } } diff --git a/src/scheduler/src/resource.c b/src/scheduler/src/resource.c index 0707fb7e..77367283 100644 --- a/src/scheduler/src/resource.c +++ b/src/scheduler/src/resource.c @@ -909,22 +909,53 @@ static float get_resval_by_id(xvec_idval_t* vec, int idx) return 0.0; } -int sched_fill_limit_requests(xce_scheduler_t* sched, xvec_idval_t* vec, +int sched_fill_limit_requests(xce_sched_alloc_req_t* alloc_req, xlist_t* limits) { int i; for (i = 0; i < limits->count; i++) { - xce_vres_t* vres = (xce_vres_t*)xlist_get(limits, i); - float val = 0.0; + xce_vres_t* vres = (xce_vres_t*)xlist_get(limits, i); + xvec_idval_t* src; + xvec_idval_t* dst; + float val = 0.0; if (vres == NULL) { continue; } - val = get_resval_by_id(vec, vres->res->idx); + /* bug-1789: a limit's own scope (global vs host -- which of + * alloc_req->shared/.host its OWN virtual resource entry, + * vres->vres, gets written into) is independent of its + * UNDERLYING resource's (vres->res) own nature. "slots" is a + * per-host resource (not XCE_RESF_GLOBAL) even when the limit + * built on top of it is global (e.g. limits.yaml's + * ug1_normal_slots, summing slots across the whole cluster) -- + * reading its want from `dst` itself (as this used to, via a + * caller-supplied `vec` equal to `dst`) silently missed every + * time for such a limit, since seqjob_prepare_allocation()/ + * parjob_prepare_allocation() only ever stage a per-host + * resource's want into alloc_req->host, never alloc_req->shared, + * regardless of which phase is running. + * + * Both `src` (where the underlying resource's want lives) and + * `dst` (where THIS limit's own vres entry belongs) are fully + * derivable from each resource's own XCE_RESF_GLOBAL flag -- + * `vres->res`'s flag is the SAME one calc_wanted_global_resvals()/ + * calc_wanted_host_resvals() (resreq.c) dispatch on to decide + * where THEY write a resource's want; `vres->vres`'s flag was set + * by instantiate_limit()->add_vres() from the exact same + * is_host_based_limit() call that decided whether this limit + * landed in obj->glimits or obj->hlimits in the first place -- so + * no caller-supplied vec is needed at all. */ + src = ((vres->res->flags & XCE_RESF_GLOBAL) != 0) ? &(alloc_req->shared) + : &(alloc_req->host); + dst = ((vres->vres->flags & XCE_RESF_GLOBAL) != 0) ? &(alloc_req->shared) + : &(alloc_req->host); - xvec_idval_store(vec, vres->vres->idx, val); + val = get_resval_by_id(src, vres->res->idx); + + xvec_idval_store(dst, vres->vres->idx, val); } return 0; diff --git a/src/scheduler/testsuite/test_driver_session_ordering.c b/src/scheduler/testsuite/test_driver_session_ordering.c index 4791a108..6fffbad4 100644 --- a/src/scheduler/testsuite/test_driver_session_ordering.c +++ b/src/scheduler/testsuite/test_driver_session_ordering.c @@ -240,11 +240,10 @@ int sched_publish_pend_reason(xce_scheduler_t* sched, xce_preason_set_t* r) * plugin.c's plugin_prepare_allocation() references it; never actually * invoked here (this test never calls plugin_prepare_allocation()). See * file header comment. */ -int sched_fill_limit_requests(xce_scheduler_t* sched, xvec_idval_t* vec, +int sched_fill_limit_requests(xce_sched_alloc_req_t* alloc_req, xlist_t* limits) { - (void)sched; - (void)vec; + (void)alloc_req; (void)limits; return 0; } diff --git a/src/scheduler/testsuite/test_maxtasks_wiring_sim_driver_parity.c b/src/scheduler/testsuite/test_maxtasks_wiring_sim_driver_parity.c index cb45f138..99a74b81 100644 --- a/src/scheduler/testsuite/test_maxtasks_wiring_sim_driver_parity.c +++ b/src/scheduler/testsuite/test_maxtasks_wiring_sim_driver_parity.c @@ -174,11 +174,10 @@ int sched_reconcile_job_resource_usage(xce_sched_core_t* c, void sched_worker_release_host_ctx(xce_sched_worker_t* w) { (void)w; } -int sched_fill_limit_requests(xce_scheduler_t* sched, xvec_idval_t* vec, +int sched_fill_limit_requests(xce_sched_alloc_req_t* alloc_req, xlist_t* limits) { - (void)sched; - (void)vec; + (void)alloc_req; (void)limits; return 0; } diff --git a/src/scheduler/testsuite/test_picker_wiring.c b/src/scheduler/testsuite/test_picker_wiring.c index 84c3dafe..489194fa 100644 --- a/src/scheduler/testsuite/test_picker_wiring.c +++ b/src/scheduler/testsuite/test_picker_wiring.c @@ -128,11 +128,10 @@ void sched_worker_release_host_ctx(xce_sched_worker_t* w) { (void)w; } /* plugin.c's plugin_prepare_allocation() (a category unrelated to picker * resolution) calls this -- stub matching test_plugin_picker_registration.c's * own. */ -int sched_fill_limit_requests(xce_scheduler_t* sched, xvec_idval_t* req, +int sched_fill_limit_requests(xce_sched_alloc_req_t* alloc_req, xlist_t* limits) { - (void)sched; - (void)req; + (void)alloc_req; (void)limits; return 0; } diff --git a/src/scheduler/testsuite/test_plugin_picker_registration.c b/src/scheduler/testsuite/test_plugin_picker_registration.c index 9057912b..f66a8990 100644 --- a/src/scheduler/testsuite/test_plugin_picker_registration.c +++ b/src/scheduler/testsuite/test_plugin_picker_registration.c @@ -37,11 +37,10 @@ * same way test_handlers.c stubs sched_init_config/sched_get_job: this * test never exercises plugin_prepare_allocation, so a no-op body is * sufficient to satisfy the linker. */ -int sched_fill_limit_requests(xce_scheduler_t* sched, xvec_idval_t* req, +int sched_fill_limit_requests(xce_sched_alloc_req_t* alloc_req, xlist_t* limits) { - (void)sched; - (void)req; + (void)alloc_req; (void)limits; return 0; } diff --git a/src/scheduler/testsuite/test_record_lifecycle.c b/src/scheduler/testsuite/test_record_lifecycle.c index 723c3480..f3c4eeb6 100644 --- a/src/scheduler/testsuite/test_record_lifecycle.c +++ b/src/scheduler/testsuite/test_record_lifecycle.c @@ -147,11 +147,10 @@ int sched_publish_pend_reason(xce_scheduler_t* sched, xce_preason_set_t* r) /* Link-satisfying stub for resource.c's sched_fill_limit_requests() -- * plugin.c's plugin_prepare_allocation() references it; never actually * invoked here. */ -int sched_fill_limit_requests(xce_scheduler_t* sched, xvec_idval_t* vec, +int sched_fill_limit_requests(xce_sched_alloc_req_t* alloc_req, xlist_t* limits) { - (void)sched; - (void)vec; + (void)alloc_req; (void)limits; return 0; } diff --git a/src/scheduler/testsuite/test_repl_breakpoints_inspection.c b/src/scheduler/testsuite/test_repl_breakpoints_inspection.c index 8a8b18fe..8eaf4852 100644 --- a/src/scheduler/testsuite/test_repl_breakpoints_inspection.c +++ b/src/scheduler/testsuite/test_repl_breakpoints_inspection.c @@ -115,11 +115,10 @@ int sched_reconcile_job_resource_usage(xce_sched_core_t* c, void sched_worker_release_host_ctx(xce_sched_worker_t* w) { (void)w; } -int sched_fill_limit_requests(xce_scheduler_t* sched, xvec_idval_t* vec, +int sched_fill_limit_requests(xce_sched_alloc_req_t* alloc_req, xlist_t* limits) { - (void)sched; - (void)vec; + (void)alloc_req; (void)limits; return 0; } diff --git a/src/scheduler/testsuite/test_repl_equivalence.c b/src/scheduler/testsuite/test_repl_equivalence.c index 18ec97e2..033f91a6 100644 --- a/src/scheduler/testsuite/test_repl_equivalence.c +++ b/src/scheduler/testsuite/test_repl_equivalence.c @@ -164,11 +164,10 @@ int sched_reconcile_job_resource_usage(xce_sched_core_t* c, void sched_worker_release_host_ctx(xce_sched_worker_t* w) { (void)w; } -int sched_fill_limit_requests(xce_scheduler_t* sched, xvec_idval_t* vec, +int sched_fill_limit_requests(xce_sched_alloc_req_t* alloc_req, xlist_t* limits) { - (void)sched; - (void)vec; + (void)alloc_req; (void)limits; return 0; } diff --git a/src/scheduler/testsuite/test_repl_event_echo.c b/src/scheduler/testsuite/test_repl_event_echo.c index b340c45e..42db6797 100644 --- a/src/scheduler/testsuite/test_repl_event_echo.c +++ b/src/scheduler/testsuite/test_repl_event_echo.c @@ -132,11 +132,10 @@ int sched_reconcile_job_resource_usage(xce_sched_core_t* c, void sched_worker_release_host_ctx(xce_sched_worker_t* w) { (void)w; } -int sched_fill_limit_requests(xce_scheduler_t* sched, xvec_idval_t* vec, +int sched_fill_limit_requests(xce_sched_alloc_req_t* alloc_req, xlist_t* limits) { - (void)sched; - (void)vec; + (void)alloc_req; (void)limits; return 0; } diff --git a/src/scheduler/testsuite/test_repl_execution_control.c b/src/scheduler/testsuite/test_repl_execution_control.c index d0cfa843..f8fc2ee8 100644 --- a/src/scheduler/testsuite/test_repl_execution_control.c +++ b/src/scheduler/testsuite/test_repl_execution_control.c @@ -129,11 +129,10 @@ int sched_reconcile_job_resource_usage(xce_sched_core_t* c, void sched_worker_release_host_ctx(xce_sched_worker_t* w) { (void)w; } -int sched_fill_limit_requests(xce_scheduler_t* sched, xvec_idval_t* vec, +int sched_fill_limit_requests(xce_sched_alloc_req_t* alloc_req, xlist_t* limits) { - (void)sched; - (void)vec; + (void)alloc_req; (void)limits; return 0; } diff --git a/src/scheduler/testsuite/test_repl_help.c b/src/scheduler/testsuite/test_repl_help.c index 70ec3059..d755913f 100644 --- a/src/scheduler/testsuite/test_repl_help.c +++ b/src/scheduler/testsuite/test_repl_help.c @@ -124,11 +124,10 @@ int sched_reconcile_job_resource_usage(xce_sched_core_t* c, void sched_worker_release_host_ctx(xce_sched_worker_t* w) { (void)w; } -int sched_fill_limit_requests(xce_scheduler_t* sched, xvec_idval_t* vec, +int sched_fill_limit_requests(xce_sched_alloc_req_t* alloc_req, xlist_t* limits) { - (void)sched; - (void)vec; + (void)alloc_req; (void)limits; return 0; } diff --git a/src/scheduler/testsuite/test_repl_prompt_context.c b/src/scheduler/testsuite/test_repl_prompt_context.c index e9855054..c1773e77 100644 --- a/src/scheduler/testsuite/test_repl_prompt_context.c +++ b/src/scheduler/testsuite/test_repl_prompt_context.c @@ -126,11 +126,10 @@ int sched_reconcile_job_resource_usage(xce_sched_core_t* c, void sched_worker_release_host_ctx(xce_sched_worker_t* w) { (void)w; } -int sched_fill_limit_requests(xce_scheduler_t* sched, xvec_idval_t* vec, +int sched_fill_limit_requests(xce_sched_alloc_req_t* alloc_req, xlist_t* limits) { - (void)sched; - (void)vec; + (void)alloc_req; (void)limits; return 0; } diff --git a/src/scheduler/testsuite/test_repl_resource_table.c b/src/scheduler/testsuite/test_repl_resource_table.c index 150312c4..a19db2d6 100644 --- a/src/scheduler/testsuite/test_repl_resource_table.c +++ b/src/scheduler/testsuite/test_repl_resource_table.c @@ -95,11 +95,10 @@ int sched_reconcile_job_resource_usage(xce_sched_core_t* c, void sched_worker_release_host_ctx(xce_sched_worker_t* w) { (void)w; } -int sched_fill_limit_requests(xce_scheduler_t* sched, xvec_idval_t* vec, +int sched_fill_limit_requests(xce_sched_alloc_req_t* alloc_req, xlist_t* limits) { - (void)sched; - (void)vec; + (void)alloc_req; (void)limits; return 0; } diff --git a/src/scheduler/testsuite/test_repl_round_rollup.c b/src/scheduler/testsuite/test_repl_round_rollup.c index d4191514..c3be19c0 100644 --- a/src/scheduler/testsuite/test_repl_round_rollup.c +++ b/src/scheduler/testsuite/test_repl_round_rollup.c @@ -91,11 +91,10 @@ int sched_reconcile_job_resource_usage(xce_sched_core_t* c, void sched_worker_release_host_ctx(xce_sched_worker_t* w) { (void)w; } -int sched_fill_limit_requests(xce_scheduler_t* sched, xvec_idval_t* vec, +int sched_fill_limit_requests(xce_sched_alloc_req_t* alloc_req, xlist_t* limits) { - (void)sched; - (void)vec; + (void)alloc_req; (void)limits; return 0; } diff --git a/src/scheduler/testsuite/test_repl_snapshot_params.c b/src/scheduler/testsuite/test_repl_snapshot_params.c index 103bd7e6..4892ca47 100644 --- a/src/scheduler/testsuite/test_repl_snapshot_params.c +++ b/src/scheduler/testsuite/test_repl_snapshot_params.c @@ -104,11 +104,10 @@ int sched_reconcile_job_resource_usage(xce_sched_core_t* c, void sched_worker_release_host_ctx(xce_sched_worker_t* w) { (void)w; } -int sched_fill_limit_requests(xce_scheduler_t* sched, xvec_idval_t* vec, +int sched_fill_limit_requests(xce_sched_alloc_req_t* alloc_req, xlist_t* limits) { - (void)sched; - (void)vec; + (void)alloc_req; (void)limits; return 0; } diff --git a/src/scheduler/testsuite/test_repl_step_verbosity.c b/src/scheduler/testsuite/test_repl_step_verbosity.c index f5a2888c..6d418ffd 100644 --- a/src/scheduler/testsuite/test_repl_step_verbosity.c +++ b/src/scheduler/testsuite/test_repl_step_verbosity.c @@ -145,11 +145,10 @@ int sched_reconcile_job_resource_usage(xce_sched_core_t* c, void sched_worker_release_host_ctx(xce_sched_worker_t* w) { (void)w; } -int sched_fill_limit_requests(xce_scheduler_t* sched, xvec_idval_t* vec, +int sched_fill_limit_requests(xce_sched_alloc_req_t* alloc_req, xlist_t* limits) { - (void)sched; - (void)vec; + (void)alloc_req; (void)limits; return 0; } diff --git a/src/scheduler/testsuite/test_resource_accounting.c b/src/scheduler/testsuite/test_resource_accounting.c index 4fb39573..01e15d09 100644 --- a/src/scheduler/testsuite/test_resource_accounting.c +++ b/src/scheduler/testsuite/test_resource_accounting.c @@ -816,6 +816,222 @@ static void test_ctx_uncommit_host_reverses_provisional_debit(void) TEST_ASSERT_EQUAL_FLOAT(0.0f, ((float*)uncomit->data)[UNCOMMIT_RESIDX]); } +/* + * bug-1789: sched_fill_limit_requests() (resource.c) computes, for each + * matched limit, how many units of the limit's own virtual resource + * (vres->vres) a job wants -- by reading how many units of the limit's + * UNDERLYING resource (vres->res) the job already requested. Both the + * READ source and the WRITE destination are one of alloc_req->shared/ + * .host, each independently chosen by that resource's own + * XCE_RESF_GLOBAL flag: vres->res's flag decides the read source, the + * SAME flag calc_wanted_global_resvals()/calc_wanted_host_resvals() + * (resreq.c) dispatch on to decide where THEY write it; vres->vres's own + * flag (set by instantiate_limit()->add_vres() from the same + * is_host_based_limit() call that put this limit in obj->glimits vs + * obj->hlimits in the first place) decides the write destination -- no + * caller-supplied vector needed for either side. These two flags are + * independent: "slots" is per-host (not XCE_RESF_GLOBAL) even when the + * limit built on it is GLOBAL (limits.yaml's ug1_normal_slots, summing + * slots across the whole cluster) -- seqjob_prepare_allocation()/ + * parjob_prepare_allocation() only ever stage a per-host resource's want + * into alloc_req->host, never alloc_req->shared, regardless of phase. + * This test proves the GLOBAL-limit/per-host-resource combination + * (bug-1789's actual reported case): the limit's own vres is + * GLOBAL-flagged (write target alloc_req->shared), but its underlying + * resource is not (its want must be read from alloc_req->host). + */ +static void +test_fill_limit_requests_global_limit_on_host_resource_reads_host(void) +{ + xce_scheduler_t sched; + xce_resource_t slots_res_in = { 0 }; + xce_resource_t limit_res_in = { 0 }; + xce_resource_t* slots_res; + xce_resource_t* limit_res; + xce_sched_alloc_req_t alloc_req; + xlist_t limits; + xce_vres_t vres; + int rc; + + memset(&sched, 0, sizeof(sched)); + TEST_ASSERT_EQUAL_INT(0, xce_sched_core_init(&(sched.core))); + + /* "slots" -- deliberately NOT XCE_RESF_GLOBAL, matching the real + * makeResource() call every host-capacity resource in this codebase + * goes through. */ + slots_res_in.name = strdup("slots"); + slots_res = makeResource(sched.core.resmgr, &slots_res_in); + TEST_ASSERT_NOT_NULL(slots_res); + + /* the LIMIT's own virtual resource -- GLOBAL, exactly as + * instantiate_limit()->add_vres() would flag it for a limit like + * ug1_normal_slots (is_host_based_limit() == 0). */ + limit_res_in.name = strdup("limit=ug1_normal_slots"); + limit_res_in.flags = XCE_RESF_GLOBAL; + limit_res = makeResource(sched.core.resmgr, &limit_res_in); + TEST_ASSERT_NOT_NULL(limit_res); + + memset(&vres, 0, sizeof(vres)); + vres.res = slots_res; + vres.vres = limit_res; + + rc = xlist_init(&limits, 4); + TEST_ASSERT_EQUAL_INT(0, rc); + rc = xlist_store(&limits, &vres); + TEST_ASSERT_TRUE(rc >= 0); + + rc = xvec_idval_init(&(alloc_req.shared), 8); + TEST_ASSERT_EQUAL_INT(0, rc); + rc = xvec_idval_init(&(alloc_req.host), 8); + TEST_ASSERT_EQUAL_INT(0, rc); + /* pre-staged into .host, as seqjob/parjob_prepare_allocation() always + * do for "slots" regardless of phase -- .shared (this limit's own + * write target, derived from limit_res's GLOBAL flag) starts empty. */ + rc = xvec_idval_store(&(alloc_req.host), slots_res->idx, 6.0f); + TEST_ASSERT_TRUE(rc >= 0); + + rc = sched_fill_limit_requests(&alloc_req, &limits); + TEST_ASSERT_EQUAL_INT(0, rc); + + TEST_ASSERT_EQUAL_INT(1, alloc_req.shared.count); + TEST_ASSERT_EQUAL_INT(limit_res->idx, ((int*)alloc_req.shared.idxs.data)[0]); + TEST_ASSERT_EQUAL_FLOAT(6.0f, ((float*)alloc_req.shared.vals.data)[0]); + /* .host stays exactly as pre-staged -- the limit's own vres entry + * went to .shared, nothing new was written to .host. */ + TEST_ASSERT_EQUAL_INT(1, alloc_req.host.count); + + xlist_fini(&limits); +} + +/* + * bug-1789 (already-working sibling case, unaffected by the fix): a + * HOST-scoped limit (its own vres NOT GLOBAL-flagged, so its write + * target is alloc_req->host) on a per-host resource (e.g. "mem", also + * not XCE_RESF_GLOBAL) reads from alloc_req->host too -- same vector as + * its own write target, exactly as before this fix. + */ +static void +test_fill_limit_requests_host_limit_on_host_resource_reads_host(void) +{ + xce_scheduler_t sched; + xce_resource_t mem_res_in = { 0 }; + xce_resource_t limit_res_in = { 0 }; + xce_resource_t* mem_res; + xce_resource_t* limit_res; + xce_sched_alloc_req_t alloc_req; + xlist_t limits; + xce_vres_t vres; + int rc; + + memset(&sched, 0, sizeof(sched)); + TEST_ASSERT_EQUAL_INT(0, xce_sched_core_init(&(sched.core))); + + mem_res_in.name = strdup(SCHED_MEM_RESOURCE_NAME); + mem_res = makeResource(sched.core.resmgr, &mem_res_in); + TEST_ASSERT_NOT_NULL(mem_res); + + /* the LIMIT's own virtual resource -- NOT GLOBAL (host-scoped limit, + * is_host_based_limit() == 1); flags left at the struct's zero + * default is sufficient, mirroring add_vres()'s XCE_RESF_DEFAULT_HOST + * (not GLOBAL) branch. */ + limit_res_in.name = strdup("limit=mem_cap"); + limit_res = makeResource(sched.core.resmgr, &limit_res_in); + TEST_ASSERT_NOT_NULL(limit_res); + + memset(&vres, 0, sizeof(vres)); + vres.res = mem_res; + vres.vres = limit_res; + + rc = xlist_init(&limits, 4); + TEST_ASSERT_EQUAL_INT(0, rc); + rc = xlist_store(&limits, &vres); + TEST_ASSERT_TRUE(rc >= 0); + + rc = xvec_idval_init(&(alloc_req.shared), 8); + TEST_ASSERT_EQUAL_INT(0, rc); + rc = xvec_idval_init(&(alloc_req.host), 8); + TEST_ASSERT_EQUAL_INT(0, rc); + /* pre-staged, as calc_wanted_host_resvals() would have already done + * for a real "mem" rusage want. */ + rc = xvec_idval_store(&(alloc_req.host), mem_res->idx, 3.0f); + TEST_ASSERT_TRUE(rc >= 0); + + rc = sched_fill_limit_requests(&alloc_req, &limits); + TEST_ASSERT_EQUAL_INT(0, rc); + + TEST_ASSERT_EQUAL_INT(2, alloc_req.host.count); + TEST_ASSERT_EQUAL_INT(limit_res->idx, ((int*)alloc_req.host.idxs.data)[1]); + TEST_ASSERT_EQUAL_FLOAT(3.0f, ((float*)alloc_req.host.vals.data)[1]); + + xlist_fini(&limits); +} + +/* + * bug-1789 (symmetric case, proves the dispatch is a genuine flag-based + * rule and not a "slots" special case): a HOST-scoped limit (its own + * vres NOT GLOBAL-flagged, so its write target is alloc_req->host) on a + * resource that IS XCE_RESF_GLOBAL (e.g. a pooled license count) must + * read from alloc_req->shared instead -- the opposite vector from its + * write target, mirroring exactly how calc_wanted_global_resvals() is + * the only one of the pair that ever populates a GLOBAL-flagged + * resource's want. + */ +static void +test_fill_limit_requests_host_limit_on_global_resource_reads_shared(void) +{ + xce_scheduler_t sched; + xce_resource_t license_res_in = { 0 }; + xce_resource_t limit_res_in = { 0 }; + xce_resource_t* license_res; + xce_resource_t* limit_res; + xce_sched_alloc_req_t alloc_req; + xlist_t limits; + xce_vres_t vres; + int rc; + + memset(&sched, 0, sizeof(sched)); + TEST_ASSERT_EQUAL_INT(0, xce_sched_core_init(&(sched.core))); + + license_res_in.name = strdup("licenses"); + license_res_in.flags = XCE_RESF_GLOBAL; + license_res = makeResource(sched.core.resmgr, &license_res_in); + TEST_ASSERT_NOT_NULL(license_res); + + /* the LIMIT's own virtual resource -- NOT GLOBAL (host-scoped limit), + * same rationale as the sibling test above. */ + limit_res_in.name = strdup("limit=license_cap"); + limit_res = makeResource(sched.core.resmgr, &limit_res_in); + TEST_ASSERT_NOT_NULL(limit_res); + + memset(&vres, 0, sizeof(vres)); + vres.res = license_res; + vres.vres = limit_res; + + rc = xlist_init(&limits, 4); + TEST_ASSERT_EQUAL_INT(0, rc); + rc = xlist_store(&limits, &vres); + TEST_ASSERT_TRUE(rc >= 0); + + rc = xvec_idval_init(&(alloc_req.shared), 8); + TEST_ASSERT_EQUAL_INT(0, rc); + rc = xvec_idval_init(&(alloc_req.host), 8); + TEST_ASSERT_EQUAL_INT(0, rc); + /* pre-staged into .shared (this job's earlier global-phase pass), NOT + * .host -- .host (this limit's own write target, derived from + * limit_res's non-GLOBAL flag) starts empty. */ + rc = xvec_idval_store(&(alloc_req.shared), license_res->idx, 5.0f); + TEST_ASSERT_TRUE(rc >= 0); + + rc = sched_fill_limit_requests(&alloc_req, &limits); + TEST_ASSERT_EQUAL_INT(0, rc); + + TEST_ASSERT_EQUAL_INT(1, alloc_req.host.count); + TEST_ASSERT_EQUAL_INT(limit_res->idx, ((int*)alloc_req.host.idxs.data)[0]); + TEST_ASSERT_EQUAL_FLOAT(5.0f, ((float*)alloc_req.host.vals.data)[0]); + + xlist_fini(&limits); +} + int main(void) { UNITY_BEGIN(); @@ -834,5 +1050,8 @@ int main(void) RUN_TEST(test_reconcile_job_resource_usage_noop_when_mem_not_a_registered_resource); RUN_TEST(test_reconcile_job_resource_usage_null_args_return_einval); RUN_TEST(test_ctx_uncommit_host_reverses_provisional_debit); + RUN_TEST(test_fill_limit_requests_global_limit_on_host_resource_reads_host); + RUN_TEST(test_fill_limit_requests_host_limit_on_host_resource_reads_host); + RUN_TEST(test_fill_limit_requests_host_limit_on_global_resource_reads_shared); return UNITY_END(); } diff --git a/src/scheduler/testsuite/test_sim_alt_events.c b/src/scheduler/testsuite/test_sim_alt_events.c index 0bbb033c..92e61a89 100644 --- a/src/scheduler/testsuite/test_sim_alt_events.c +++ b/src/scheduler/testsuite/test_sim_alt_events.c @@ -123,11 +123,10 @@ int sched_reconcile_job_resource_usage(xce_sched_core_t* c, (void)c; (void)a; (void)r; return 0; } -int sched_fill_limit_requests(xce_scheduler_t* sched, xvec_idval_t* vec, +int sched_fill_limit_requests(xce_sched_alloc_req_t* alloc_req, xlist_t* limits) { - (void)sched; - (void)vec; + (void)alloc_req; (void)limits; return 0; } diff --git a/src/scheduler/testsuite/test_sim_equivalence.c b/src/scheduler/testsuite/test_sim_equivalence.c index 3226cf9a..38b26443 100644 --- a/src/scheduler/testsuite/test_sim_equivalence.c +++ b/src/scheduler/testsuite/test_sim_equivalence.c @@ -196,11 +196,10 @@ void sched_worker_release_host_ctx(xce_sched_worker_t* w) { (void)w; } /* plugin_prepare_allocation()'s (plugin.c) linker dependency -- never * invoked (this fixture never drives real resource-matching allocation -- * see this file's header comment). */ -int sched_fill_limit_requests(xce_scheduler_t* sched, xvec_idval_t* vec, +int sched_fill_limit_requests(xce_sched_alloc_req_t* alloc_req, xlist_t* limits) { - (void)sched; - (void)vec; + (void)alloc_req; (void)limits; return 0; } diff --git a/src/scheduler/testsuite/test_sim_event_loop.c b/src/scheduler/testsuite/test_sim_event_loop.c index a715dff6..f4af0579 100644 --- a/src/scheduler/testsuite/test_sim_event_loop.c +++ b/src/scheduler/testsuite/test_sim_event_loop.c @@ -144,11 +144,10 @@ void sched_worker_release_host_ctx(xce_sched_worker_t* w) { (void)w; } /* plugin_prepare_allocation()'s (plugin.c, the "limit" plugin category) * linker dependency -- never invoked (this file never drives real * allocation, Req 5 AC 17 / this file's own header comment). */ -int sched_fill_limit_requests(xce_scheduler_t* sched, xvec_idval_t* vec, +int sched_fill_limit_requests(xce_sched_alloc_req_t* alloc_req, xlist_t* limits) { - (void)sched; - (void)vec; + (void)alloc_req; (void)limits; return 0; } diff --git a/src/scheduler/testsuite/test_sim_print_decision_gate.c b/src/scheduler/testsuite/test_sim_print_decision_gate.c index 5d5999c4..ce4adf95 100644 --- a/src/scheduler/testsuite/test_sim_print_decision_gate.c +++ b/src/scheduler/testsuite/test_sim_print_decision_gate.c @@ -150,11 +150,10 @@ int sched_reconcile_job_resource_usage(xce_sched_core_t* c, void sched_worker_release_host_ctx(xce_sched_worker_t* w) { (void)w; } -int sched_fill_limit_requests(xce_scheduler_t* sched, xvec_idval_t* vec, +int sched_fill_limit_requests(xce_sched_alloc_req_t* alloc_req, xlist_t* limits) { - (void)sched; - (void)vec; + (void)alloc_req; (void)limits; return 0; } diff --git a/src/scheduler/testsuite/test_sim_record_output.c b/src/scheduler/testsuite/test_sim_record_output.c index 6653bd96..c8ce2dc0 100644 --- a/src/scheduler/testsuite/test_sim_record_output.c +++ b/src/scheduler/testsuite/test_sim_record_output.c @@ -109,11 +109,10 @@ int sched_reconcile_job_resource_usage(xce_sched_core_t* c, void sched_worker_release_host_ctx(xce_sched_worker_t* w) { (void)w; } -int sched_fill_limit_requests(xce_scheduler_t* sched, xvec_idval_t* vec, +int sched_fill_limit_requests(xce_sched_alloc_req_t* alloc_req, xlist_t* limits) { - (void)sched; - (void)vec; + (void)alloc_req; (void)limits; return 0; } diff --git a/src/scheduler/testsuite/test_sim_session_ordering.c b/src/scheduler/testsuite/test_sim_session_ordering.c index 8d4ede3d..cb33deca 100644 --- a/src/scheduler/testsuite/test_sim_session_ordering.c +++ b/src/scheduler/testsuite/test_sim_session_ordering.c @@ -180,11 +180,10 @@ int sched_reconcile_job_resource_usage(xce_sched_core_t* c, /* plugin_prepare_allocation()'s (plugin.c) linker dependency -- never * invoked (this fixture never drives real resource-matching allocation -- * same rationale test_sim_equivalence.c's own copy documents). */ -int sched_fill_limit_requests(xce_scheduler_t* sched, xvec_idval_t* vec, +int sched_fill_limit_requests(xce_sched_alloc_req_t* alloc_req, xlist_t* limits) { - (void)sched; - (void)vec; + (void)alloc_req; (void)limits; return 0; } diff --git a/src/scheduler/testsuite/test_sim_snapshot_reconcile_gap.c b/src/scheduler/testsuite/test_sim_snapshot_reconcile_gap.c index f869c6df..ec4068f2 100644 --- a/src/scheduler/testsuite/test_sim_snapshot_reconcile_gap.c +++ b/src/scheduler/testsuite/test_sim_snapshot_reconcile_gap.c @@ -136,11 +136,10 @@ int sched_reconcile_job_resource_usage(xce_sched_core_t* c, /* plugin_prepare_allocation()'s (plugin.c, the "limit" plugin category) * linker dependency -- never invoked (this file never drives real * allocation). */ -int sched_fill_limit_requests(xce_scheduler_t* sched, xvec_idval_t* vec, +int sched_fill_limit_requests(xce_sched_alloc_req_t* alloc_req, xlist_t* limits) { - (void)sched; - (void)vec; + (void)alloc_req; (void)limits; return 0; } diff --git a/src/scheduler/testsuite/test_sim_verify.c b/src/scheduler/testsuite/test_sim_verify.c index 0c76dac2..fdd3a2d7 100644 --- a/src/scheduler/testsuite/test_sim_verify.c +++ b/src/scheduler/testsuite/test_sim_verify.c @@ -135,11 +135,10 @@ void sched_worker_release_host_ctx(xce_sched_worker_t* w) { (void)w; } /* plugin_prepare_allocation()'s (plugin.c, the "limit" plugin category) * linker dependency -- never invoked (this file never drives real * allocation). */ -int sched_fill_limit_requests(xce_scheduler_t* sched, xvec_idval_t* vec, +int sched_fill_limit_requests(xce_sched_alloc_req_t* alloc_req, xlist_t* limits) { - (void)sched; - (void)vec; + (void)alloc_req; (void)limits; return 0; }