From 828479d2aa9f668ececc866dc9cf00ee74662ebc Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Thu, 8 Oct 2026 23:39:30 -0400 Subject: vgsp-sema: only a real session end may request the discovery flush (ISSUE-0002) A redundant channel delete (a FREE for a handle that never registered, or a repeated delete after the session already ended) found the channel set empty while the next client was already starting and re-armed the flush, which then executed mid-startup and wiped that client's discovery state (and dropped its pending releases): the client spun at its first channel. Track whether a session's channel has registered since the last flush and request the flush only on the true existed->empty transition; redundant deletes are inert. --- kernel/gsp_sema_service.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'kernel/gsp_sema_service.c') diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index 3b56c36..715e458 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -406,6 +406,7 @@ static u32 svc_ring_n; * rebuild start from the same empty state as a fresh boot. */ static u8 svc_sess_flush; +static u8 svc_sess_active; /* a channel of a session has registered (until flush) */ static unsigned long svc_ring_done; /* CE ranks whose ring is pinned (session state) */ static u8 svc_pb_passes; static u64 svc_pb_last; @@ -925,6 +926,7 @@ void gsp_sema_service_channel_add(const struct sema_channel_desc *desc) ch->gr_index = rank; } ch->valid = true; + svc_sess_active = 1; ch->h_object = desc->h_object; ch->engine_type = desc->engine_type; ch->cid = desc->cid; @@ -986,14 +988,21 @@ void gsp_sema_service_channel_del(u32 h_object) * session in a new UVM VA space; its discovery state must not inherit * this session's map/pins/page-directory latch. Request the flush * here; it executes at the next rebuild (the only writer of that - * state) just like a fresh boot would start empty. + * state) just like a fresh boot would start empty. Only the transition + * from "a session existed" to "empty" may request it: redundant + * deletes for handles that never registered would otherwise re-flush + * (and wipe) a session that started after the real one ended. */ - for (i = 0; i < SVC_MAX_CHANNELS; i++) { - if (svc.chan[i].valid) - break; + if (svc_sess_active) { + for (i = 0; i < SVC_MAX_CHANNELS; i++) { + if (svc.chan[i].valid) + break; + } + if (i == SVC_MAX_CHANNELS) { + svc_sess_active = 0; + svc_sess_flush = 1; + } } - if (i == SVC_MAX_CHANNELS) - svc_sess_flush = 1; spin_unlock_irqrestore(&svc.chan_lock, flags); /* -- cgit v1.2.3