rdma: add terminal notification callback to the RC server ABI

RC sessions that never reach a completion (expired, abandoned, or canceled before READY) currently vanish inside the reaper without any trace on the operational surface. Add a terminal notification callback to the C ABI so the server reports the final outcome of every session exactly once, fired from the reaper with no server lock held.
This commit is contained in:
Jihyeon Gim
2026-09-09 13:16:52 +09:00
parent 7c49bb4513
commit 138504dbc9
2 changed files with 34 additions and 0 deletions
+19
View File
@@ -101,6 +101,11 @@ struct rc_server {
* races an in-flight sink pointer swap. */
rc_log_fn log_fn = nullptr;
void *log_ctx = nullptr;
/* Terminal notification sink: same lifetime contract as log_fn
* (installed once at init, cleared by destroy after the reaper
* joined). Fired by reapSession with no lock held. */
rc_terminal_fn term_fn = nullptr;
void *term_ctx = nullptr;
std::atomic<uint64_t> epoch_counter{1};
/* resource accounting (global buckets; per-principal map). */
std::mutex acct_mtx;
@@ -253,6 +258,13 @@ void reapSession(rc_server *srv, RcSession *s) {
* is actually gone: a surviving QP still holds the device. */
if (destroyed) hipObj::v2::releaseDevice(srv->device);
limitsRelease(srv, s->principal, s->staging_len);
/* Terminal notification: the sink runs after every server-side
* bookkeeping above so it observes the session as fully gone,
* and no lock is held here per the callback contract. */
rc_terminal_fn tfn = srv->term_fn;
if (tfn)
tfn(srv->term_ctx, s->core.id.c_str(), s->last_outcome,
(uint64_t)s->staging_len);
}
/* Runs the reap pass: sessions marked reap_pending (or in the
@@ -301,6 +313,13 @@ void rc_server_set_log_sink(rc_server *srv, rc_log_fn fn, void *ctx) {
srv->log_ctx = ctx;
}
void rc_server_set_terminal_notify(rc_server *srv, rc_terminal_fn fn,
void *ctx) {
if (!srv) return;
srv->term_fn = fn;
srv->term_ctx = ctx;
}
int rc_server_init(const rc_device_opts *opts, rc_server **out) {
if (!opts || !out) return RC_E_ARG;
if (!hipObj::ibv.ensureLoaded()) {
+15
View File
@@ -52,6 +52,21 @@ typedef struct rc_server rc_server;
void rc_server_set_log_sink(rc_server *srv, rc_log_fn fn, void *ctx);
/* Terminal session notification. Fired exactly once per session
* when the reaper destroys it (expiry, CANCEL, or destroy),
* carrying the last outcome observed for the session. `id` is
* only valid for the duration of the call. Called with no server
* lock held; the sink must return promptly and must not call back
* into the server. Sessions that end inside a READY/FinishPut
* handler still fire this notification after the handler's own
* terminal bookkeeping, so the sink can treat it as the single
* authoritative "the session is gone" signal. */
typedef void (*rc_terminal_fn)(void *ctx, const char *id, int outcome,
uint64_t bytes);
void rc_server_set_terminal_notify(rc_server *srv, rc_terminal_fn fn,
void *ctx);
/* Device selection: matching GID prefix when gid_hint is set,
* otherwise the first verbs device. */
typedef struct {