UCT/IB/MLX5: support in progress error handler - #11829
Conversation
|
🤖 CI Triage Agent — TL;DR: Two RC/mlx5 error-path gtests hung (3 min and 15 min of zero output, ending in the gtest watchdog Full analysisSummary: Root cause: Evidence of a hang, not slowness: the log jumps 07:27:15 → 07:42:15 with no output while in Implicated commit: 2123627 "UCT/IB/MLX5: add support for no completions" (Zihao Zhao), building on 106bf44 "UCT/IB/MLX5: support err handle return inprogess" File: src/uct/ib/mlx5/rc/rc_mlx5_iface.c:210-239 (with src/uct/ib/mlx5/rc/rc_mlx5_ep.c:726-775) Suggested fix: In the Related: PR #11829 ("[DNM] UCT/IB/MLX5: support in progress error handler"), prior work PR #11668 ("UCT: outstanding purge implementation") |
2123627 to
0a8d5c3
Compare
|
🤖 Starting review — findings will be posted here when done. |
| uct_ep_h tl_ep, const uct_ep_outstanding_purge_params_t *params) | ||
| { | ||
| uct_rc_mlx5_base_ep_t *ep = ucs_derived_of(tl_ep, uct_rc_mlx5_base_ep_t); | ||
| ucs_status_t status = uct_ib_mlx5_ext_ep_outstanding_purge(tl_ep, params); |
There was a problem hiding this comment.
uct_rc_mlx5_ep_update_tx_qp_res runs on the error path of the purge, using a possibly-stale ft_ci.
ucs_status_t status = uct_ib_mlx5_ext_ep_outstanding_purge(tl_ep, params);
uct_rc_mlx5_ep_update_tx_qp_res(ep, ep->tx.wq.ft_ci);
if (status != UCS_OK) {
...
return status;
}uct_ep_outstanding_purge() is a public API and can be invoked on an ep that never went through the UCS_INPROGRESS failure path, so ft_ci may still be its reset value UINT16_MAX. update_tx_qp_res then computes available = bb_max - (prev_sw_pi - UINT16_MAX), which is bogus and will trip ucs_assert(available >= prev_available) (assert builds) or corrupt txqp->available (release builds). It is also called unconditionally even when the ext purge returned UCS_ERR_UNSUPPORTED/no plugin handled it. Suggested draft comment:
can we only update tx qp res when the ext purge actually handled the ep (status == UCS_OK) and the ep is in the NO_COMPLETIONS state? otherwise
ft_ciis still UINT16_MAX andupdate_tx_qp_rescomputes a badavailable.
There was a problem hiding this comment.
It is intentional. uct_ep_outstanding_purge may partial successfully purge, when e.g. memory is insufficient. Updating resources only when status == UCS_OK would discard that committed progress and could cause double purge.
| */ | ||
| ucs_assertv(bb_num > 0, "hw_ci=%d prev_sw_pi=%d available=%d bb_num=%d", | ||
| hw_ci, txwq->prev_sw_pi, txqp->available, bb_num); | ||
| uct_ib_mlx5_txwq_t *txwq = &ep->tx.wq; |
There was a problem hiding this comment.
Switch from the update_bb formula to incremental hw_ci - prev_hw_ci assumes strict monotonicity.
uint16_t bb_num = hw_ci - prev_hw_ci;
ucs_assertv(bb_num > 0, ...);
txwq->hw_ci = hw_ci;The previous update_tx_res derived bb_num from prev_sw_pi/available, which was robust to repeated completions reporting the same counter. The new code requires every reported hw_ci/pi to strictly advance past the stored hw_ci. In handle_failure the flushed error CQEs feed pi into this function via out_update_tx_res, and this now also runs on the repeated-failure path (ERR_HANDLER_INVOKED/FLUSH_CANCEL -> goto out_update_tx_res). If a subsequent error CQE reports the same wqe_counter, bb_num == 0 trips the assert. Worth confirming that flushed error CQEs always carry a strictly increasing counter, otherwise this is a regression from the old formula.
There was a problem hiding this comment.
It's strict monotonicity. HW should not generates 2 cqes for 1 wqe.
| uct_ib_mlx5_completion_with_err(ib_iface, arg, &ep->tx.wq, log_lvl); | ||
|
|
||
| if (status == UCS_INPROGRESS) { | ||
| ep->flags |= UCT_RC_MLX5_EP_FLAG_NO_COMPLETIONS; |
There was a problem hiding this comment.
UCT_RC_MLX5_EP_FLAG_NO_COMPLETIONS is set but never cleared. Once set on the first UCS_INPROGRESS failure, subsequent handle_failure calls on the same ep permanently skip uct_rc_txqp_purge_outstanding and update_tx_qp_res, while update_tx_cq_res keeps releasing CQ credits. Please confirm this is intended (the outstanding WQEs and their QP resources are handed off to the plugin for the life of the ep) and that no later CQE on this QP needs the purge/qp-res path.
There was a problem hiding this comment.
It is intentional. Once the error handler returns UCS_INPROGRESS, UCP then decides when to purge, clean up, and destroy the endpoint. The endpoint does not return to normal completion processing.
| ep->tx.wq.ft_ci = ep->tx.wq.prev_sw_pi - | ||
| (ep->tx.wq.bb_max - | ||
| uct_rc_txqp_available(&ep->super.txqp)); | ||
| ucs_debug("ep %p outstanding WQE range (%u, %u)", ep, ep->tx.wq.ft_ci, |
There was a problem hiding this comment.
Minor: inconsistent range in the two log messages. rc_mlx5_iface.c L230 uses (ft_ci, sw_pi) while rc_mlx5_ep.c L796 uses (ft_ci, prev_sw_pi) for what reads like the same outstanding range. Pick one end consistently.
|
Notes / no action: Making Test coverage: This is a behavioral change to the RC error/purge path. I did not find an added regression test in the diff. Since the new |
|
🤖 Starting review — findings will be posted here when done. |
| uct_rc_mlx5_base_ep_t *ep = ucs_derived_of(tl_ep, uct_rc_mlx5_base_ep_t); | ||
| ucs_status_t status = uct_ib_mlx5_ext_ep_outstanding_purge(tl_ep, params); | ||
|
|
||
| uct_rc_mlx5_ep_update_tx_qp_res(ep, ep->tx.wq.ft_ci); |
There was a problem hiding this comment.
blocker: uct_rc_mlx5_ep_outstanding_purge calls uct_rc_mlx5_ep_update_tx_qp_res(ep, ep->tx.wq.ft_ci) unconditionally, before the status != UCS_OK check.
ep_outstanding_purgeis reachable from the publicuct_ep_outstanding_purgev2 API on any RC mlx5 EP, including EPs that never took thehandle_failureUCS_INPROGRESSpath. In that caseft_ciis still the reset sentinelUINT16_MAX, soupdate_tx_qp_rescomputesavailable = bb_max - (prev_sw_pi - 0xFFFF)(garbage), trippingucs_assert(available >= prev_available)or corruptingtxqp->available.- When the plugin returns an error (e.g.
UCS_ERR_UNSUPPORTEDwhen no plugin is registered), nothing was drained, so releasing QP resources is also incorrect on that path.
Suggested fix — only release QP resources after a successful purge (and it belongs after the failure early-return):
ucs_status_t uct_rc_mlx5_ep_outstanding_purge(
uct_ep_h tl_ep, const uct_ep_outstanding_purge_params_t *params)
{
uct_rc_mlx5_base_ep_t *ep = ucs_derived_of(tl_ep, uct_rc_mlx5_base_ep_t);
ucs_status_t status = uct_ib_mlx5_ext_ep_outstanding_purge(tl_ep, params);
if (status != UCS_OK) {
ucs_trace("ep %p purge outstanding range (%u, %u) status %s", ep,
ep->tx.wq.ft_ci, ep->tx.wq.sw_pi, ucs_status_string(status));
return status;
}
uct_rc_mlx5_ep_update_tx_qp_res(ep, ep->tx.wq.ft_ci);
ucs_debug("ep %p purge outstanding OK", ep);
return UCS_OK;
}Consider also gating this on ep->flags & UCT_RC_MLX5_EP_FLAG_NO_COMPLETIONS (and clearing it) so a purge that did not follow a deferred failure is a no-op for QP resources.
There was a problem hiding this comment.
It is intentional. uct_ep_outstanding_purge may partial successfully purge, when e.g. memory is insufficient. Updating resources only when status == UCS_OK would discard that committed progress and could cause double purge.
|
Test coverage: no regression test in the diff for the deferred |
|
🤖 CI Triage Agent — TL;DR: The Full analysisSummary: Root cause: At 11:49:40 the log shows:
The drop tool therefore died right after being backgrounded (confirmed later by The script has no check on the drop tool's success: line 549 launches Implicated commit: [REDACTED:Hex High Entropy String] — "CI/FT: Adds fault tolerance CI test (#11570)", william-gallagher-nv (added File: contrib/test_jenkins.sh:549 (drop tool launch, unchecked) — failure surfaces at contrib/test_jenkins.sh:557 via Suggested fix:
${drop_tool} -d ${dev} -s ${sl} -t ${tc} > drop_tool.${dev}.log 2>&1 &
drop_pid=$!
sleep 2
if ! kill -0 ${drop_pid} 2>/dev/null; then
cat drop_tool.${dev}.log
echo "Warning: drop tool failed on ${dev} (flow table not supported/permitted) - skipping FT test"
kill_background_processes "${background_pids[@]}"
return 0 # or 'continue' if other devices should still be tried
fi
background_pids+=(${drop_pid})
Related: PR #11570 (added the fault tolerance CI test); PR #11829 (this build) — no existing issue found for syndrome
|
| txwq->curr = txwq->qstart; | ||
| txwq->sw_pi = 0; | ||
| txwq->prev_sw_pi = UINT16_MAX; | ||
| txwq->ft_ci = UINT16_MAX; | ||
| txwq->hw_ci = UINT16_MAX; | ||
| #if UCS_ENABLE_ASSERT | ||
| txwq->hw_ci = 0xFFFF; | ||
| txwq->flags = 0; | ||
| txwq->flags = 0; |
There was a problem hiding this comment.
Too many spaces (about 4 too many)
| uct_rc_mlx5_base_ep_t *ep = ucs_derived_of(tl_ep, uct_rc_mlx5_base_ep_t); | ||
| ucs_status_t status = uct_ib_mlx5_ext_ep_outstanding_purge(tl_ep, params); | ||
|
|
||
| uct_rc_mlx5_ep_update_tx_qp_res(ep, ep->tx.wq.ft_ci); |
There was a problem hiding this comment.
Should we gate here with NO_COMPLETIONS flag in the EP? otherwise ft_ci value would be UINT16_MAX
we should also clean NO_COMPLETIONS flag after that
| uct_ep_h tl_ep, const uct_ep_outstanding_purge_params_t *params) | ||
| { | ||
| uct_rc_mlx5_base_ep_t *ep = ucs_derived_of(tl_ep, uct_rc_mlx5_base_ep_t); | ||
| ucs_status_t status = uct_ib_mlx5_ext_ep_outstanding_purge(tl_ep, params); |
There was a problem hiding this comment.
So that API stays in EXT?
There was a problem hiding this comment.
It can be removed in the PR for the purge implementation. In this PR it keeps the behavior the same as master. IMO, cleanup plugin call is not this PR’s responsibility. WDYT?
|
🤖 Starting review — findings will be posted here when done. |
| @@ -783,6 +783,29 @@ ucs_status_t uct_rc_mlx5_base_ep_invalidate(uct_ep_h tl_ep, | |||
| IBV_QPS_ERR); | |||
There was a problem hiding this comment.
uct_rc_mlx5_ep_outstanding_purge asserts ep->no_comp on a public API path. This function is installed as the transport's public ep_outstanding_purge op (uct_ep_outstanding_purge). The API contract does not require the ep to have first entered the deferred-completion (no_comp) state. If a caller invokes uct_ep_outstanding_purge on an ep that never failed, ep->no_comp == 0: in debug build the ucs_assert(ep->no_comp) fires; in release build ep->tx.wq.ft_ci is still UINT16_MAX (its reset value) so uct_rc_mlx5_ep_update_tx_qp_res(ep, ft_ci) computes wrong tx-qp resources. Please guard this path (return an error, or early-out) when no_comp is not set, instead of asserting it.
| } | ||
|
|
||
| ucs_status_t uct_rc_mlx5_base_ep_fc_ctrl(uct_ep_t *tl_ep, unsigned op, | ||
| uct_rc_pending_req_t *req) |
There was a problem hiding this comment.
ft_ci passed to update_tx_qp_res on purge leaves the outstanding range's tx-qp credits unreclaimed. ft_ci is set in handle_failure to the hw_ci of the first outstanding WQE: ft_ci = prev_sw_pi - (bb_max - available). Feeding that same value back into available = bb_max - (prev_sw_pi - ft_ci) recomputes exactly the pre-failure available, so the purge returns zero tx-qp resources for the just-purged range. If the intent is to reclaim the purged WQEs, this looks like it should pass sw_pi (end of the range), not ft_ci. Can you confirm the intended value here, and whether the ep is expected to be destroyed right after so the unreclaimed credits don't matter?
|
Minor: |
|
🤖 CI Triage Agent — TL;DR: The Full analysisSummary: Build of Root cause: Compiler output (log 02:12:31.83): The build uses Implicated commit: e428402 "UCT/IB/MLX5: address comments" (Zihao Zhao), on top of b27def8 "UCT/IB/MLX5: add support for no completions" (Zihao Zhao) — PR #11829 File: src/uct/ib/mlx5/rc/rc_mlx5_ep.c:825 (call site; repo copy line 794) — prototype at src/uct/ib/mlx5/ib_mlx5_ext.h:203 Suggested fix: Ensure #include <uct/ib/mlx5/ib_mlx5_log.h>
#include <uct/ib/mlx5/ib_mlx5_ext.h> /* <- required for
uct_ib_mlx5_ext_ep_outstanding_purge() */The branch tip already carries this include at Related: PR #11829 (this PR), PR #11668 (added
|
What?
Allow an RC mlx5 error handler to return UCS_INPROGRESS so the transport does not immediately purge outstanding TX WQEs.
Why?
On endpoint failure, RC mlx5 currently always purges outstanding ops and returns both CQ and QP resources in one step. Failover needs those WQEs to stay posted so the UCP can inspect or recover them.
How?
Allows error handler return UCS_INPROGRESS to indicate that completions should not be purged imediately.
Split ep invalidate from #11684