Skip to content

UCS/SYS/TOPO: Allow multiple sibling devices per memory device - #12126

Merged
tvegas1 merged 12 commits into
openucx:masterfrom
tomerg-nvidia:topo-multi-dev-sibling
Oct 30, 2026
Merged

tvegas1 merged 12 commits into
openucx:masterfrom
tomerg-nvidia:topo-multi-dev-sibling

Conversation

@tomerg-nvidia

@tomerg-nvidia tomerg-nvidia commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

What?

Topology sibling tracking now keeps a bitmap of all matched sibling devices. Before, it kept a single sibling_sys_dev per device.

Why?

On a multi-plane directNIC setup, each ConnectX-8 shows up as several plane RDMA devices that all report the same Data Direct device. The old code kept only one match, so just one plane was reachable from the GPU with Direct NIC.

How?

  • The memory-side device (MEM role) stores a bitmap of all matched devices, and each device (DEV role) stores a bitmap of its matched memory devices.
  • ucs_topo_is_reachable() now checks bitmap membership.
  • ucs_sys_device_bitmap_t moved to topo_int.h.

@svc-nvidia-pr-review

Copy link
Copy Markdown

🤖 Starting review — findings will be posted here when done.

@tomerg-nvidia
tomerg-nvidia marked this pull request as ready for review October 20, 2026 19:14
@svc-ucx

svc-ucx commented Oct 20, 2026

Copy link
Copy Markdown

🤖 CI Triage Agent — UCX PR (Tests BlueField on worker 0) · commit 8e802529

TL;DR: The BlueField gtest job failed on a single unrelated test, thread_spinlock/test_async.timer_unset_from_handler/0 (UCS async timer), while all 8887 other tests passed — this is a known-flaky timing-sensitive async test, not a regression from PR #12126 (topology sibling devices). Re-run the job; optionally harden the test's hard-coded fire-count bound.

Full analysis

Summary: make test in the gtest stage exited with error 1 because exactly 1 of 8888 tests failed: thread_spinlock/test_async.timer_unset_from_handler/0.

Root cause: Evidence from the log: [ PASSED ] 8887 tests. / [ FAILED ] 1 test ... thread_spinlock/test_async.timer_unset_from_handler/0, where GetParam() = thread_spinlock, then make: *** [Makefile:4925: test] Error 1. The test exercises ucs_async timer removal from within the timer handler and has hard-coded timing expectations:

  • local_timer_remove_handler uses a 1000 µs (TIMER_INTERVAL_USEC = 1000) periodic timer whose handler calls unset_handler(false) — i.e. asynchronous removal (test/gtest/ucs/test_async.cc:813-834).
  • The test then asserts EXPECT_LE(lt.count(), 5) with the comment "timer could fire multiple times before we remove it", and later EXPECT_EQ(count, lt.count()).

On a BlueField ARM target the progress thread dispatches expired timers in batch (ucs_async_dispatch_timerq, src/ucs/async/async.c:332-360, with ucs_timerq_for_each_expired re-arming expiration inside the lock) and epoll waits with UCS_ASYNC_EPOLL_MIN_TIMEOUT_MS = 2.0 (src/ucs/async/thread.c:23) — i.e. coarser than the 1 ms timer. Under the heavy load of a 2834-second full gtest run on slow cores, the timer can expire/dispatch more times than the fixed bound of 5 before the asynchronous handler removal takes effect, so the test's fixed numeric threshold is violated. Nothing in PR #12126 (src/ucs/sys/topo/base/topo.c, commit 8e80252 "UCS/SYS/TOPO: Allow multiple sibling devices per memory device") touches src/ucs/async/* or the timer queue, so the failure is not causally related to the change under test. This exact test has a prior flakiness record (issue #2023, same test, thread variant).

Note: the fetched log is the job tail; the failing test ran early in the run so its individual assertion message is outside the retrievable window. The attribution above is based on the test's source-level timing assumptions, not on the quoted assertion text.

Implicated commit: none — PR commit [REDACTED:Hex High Entropy String] (Tomer Gilad, topo-only change) is not implicated; the flaky test logic predates it (last functional touches: a7b71bc "UCS/ASYNC: Fix crash when async thread is not running", 2faf305 "UCS/ASYNC: Filter stale missed fd events")

File: test/gtest/ucs/test_async.cc:830 (EXPECT_LE(lt.count(), 5);), with supporting context at test/gtest/ucs/test_async.cc:264 and src/ucs/async/thread.c:23

Suggested fix:

  1. Immediate: re-trigger the "Tests BlueField on worker 0" job — this is an unrelated pre-existing flake and should not block PR UCS/SYS/TOPO: Allow multiple sibling devices per memory device #12126.
  2. Durable: make the test robust on slow/loaded ARM targets instead of relying on a magic constant. Either
    • scale the bound by the test time multiplier and the real elapsed/interval ratio, e.g. compute the allowed count from elapsed time / TIMER_INTERVAL_USEC rather than hard-coding 5, or
    • increase TIMER_INTERVAL_USEC for this specific test (e.g. 10 ms, comfortably above the 2 ms epoll floor in src/ucs/async/thread.c:23) so a single removal window cannot straddle multiple expirations, and keep EXPECT_EQ(count, lt.count()) as the real correctness check (that no further dispatch happens after removal).

Related: PR #12126 (the PR under test); prior flake report for the same test: #2023

🛡️ This comment had 1 potential secret(s) redacted (Hex High Entropy String). See request_id 14539113-f8fd-4f0b-aa26-3a1b6e3789d3 in the triage console for the audit trail.

@svc-nvidia-pr-review

Copy link
Copy Markdown

🤖 Starting review — findings will be posted here when done.

Comment thread src/ucs/sys/topo/base/topo.c Resolved
Comment thread src/ucs/sys/topo/base/topo.c Resolved
@svc-nvidia-pr-review

Copy link
Copy Markdown

Residual coverage gap worth noting: the new tests only assert ucs_topo_device_has_sibling() on the memory device, so the DEV-side bits of siblings stay unverified; and like the existing sibling test, they assume the HCA used as the negative case (m_hcas[num_planes]) is not behind the GPU's bridge, which is hardware dependent.

@svc-ucx

svc-ucx commented Oct 21, 2026

Copy link
Copy Markdown

🤖 CI Triage Agent — UCX PR (Tests gpu on worker 2) · commit 7ad02525

TL;DR: The gpu gtest run aborted on a UCT assertion — dcx/test_ucp_fault_tolerance.initiator_failure/10 <dc_x/AM|FLUSH> posted a real AM zcopy WQE on a DC send queue still flagged UCT_IB_MLX5_TXWQ_FLAG_FAILED during lane recovery. The PR's topology change lets two AM BW lanes map onto sibling NICs that share one DCI/txwq, so failing lane 0 poisons the txwq that recovery then re-posts on.

Full analysis

Summary: make test in the "gpu on worker 2" job crashed (core dumped, bash exit 2) on Assertion '!(txwq->flags & UCT_IB_MLX5_TXWQ_FLAG_FAILED)' failed at rc_mlx5.inl:498, inside dcx/test_ucp_fault_tolerance.initiator_failure/10 <dc_x/AM|FLUSH>.

Root cause: The backtrace is unambiguous: ucp_am_send_nbx → uct_dc_mlx5_ep_am_zcopy → uct_rc_mlx5_common_post_send, which asserts that only MLX5_OPCODE_NOP may be posted once a txwq is marked FAILED (src/uct/ib/mlx5/rc/rc_mlx5.inl:495-499, comment: "If FAILED, allow only NOP sends to be posted"). The log timeline shows exactly when it fires — the test picked 2 AM BW lanes ("AM BW : 0/2", "AM BW : 1/2"), injected failure on lane 0/2, the post-failure op reported "Success", and the abort happens ~600 ms later immediately after "Checking recovery status...". So the recovery path re-posted a non-NOP AM zcopy onto a send queue whose FAILED flag was still set.

The reason this surfaces on this branch: UCP failover assumes each lane has independent UCT send-queue state, but for DC the txwq belongs to a DCI shared across endpoints/lanes. PR #12126 / commit 8e802529 ("UCS/SYS/TOPO: Allow multiple sibling devices per memory device") changes GPU→NIC assignment so one memory device can select multiple sibling NICs — which changes lane selection on this dual-port GPU node (mlx5_0:1/mlx5_1:1 both in play) and allows the two dc_x AM BW lanes to resolve onto devices sharing a DCI. Marking lane 0 failed then poisons the txwq that lane 1's recovery send uses. Note the assert is in pre-existing UCT code; the topo change is what newly makes the lane-sharing configuration reachable, so the bug is the interaction, not the assert itself.

Implicated commit: 8e802529 — Tomer Gilad, "UCS/SYS/TOPO: Allow multiple sibling devices per memory device" (PR #12126, HEAD 7ad0252); assert site predates it ([REDACTED:Hex High Entropy String], Zihao Zhao).

File: src/uct/ib/mlx5/rc/rc_mlx5.inl:498 (assert) — triggered via src/uct/ib/mlx5/dc/dc_mlx5_ep.c (uct_dc_mlx5_ep_am_zcopy); root trigger in src/ucs/sys/topo/base/topo.c sibling-device assignment.

Suggested fix:

  1. Reproduce deterministically: run dcx/test_ucp_fault_tolerance.initiator_failure/10 with UCX_TLS=dc_x on a 2-NIC GPU node and dump ucp_ep_config()->key.am_bw_lanes plus each lane's resolved sys_dev/IB device and DCI index. Confirm the two AM BW lanes share a DCI — that confirms this diagnosis in one shot.
  2. If confirmed, the correct fix is on the failover side, not the topo side: lane recovery must not re-post on a lane whose underlying DCI txwq is FAILED. Either clear UCT_IB_MLX5_TXWQ_FLAG_FAILED when the DCI is reset/reconnected during recovery, or have uct_dc_mlx5_ep_am_zcopy return UCS_ERR_CONNECTION_RESET (letting UCP retry/fail over) instead of hitting the assert when the DCI is still in failed state.
  3. Complementary hardening in this PR: when selecting sibling devices for a memory device, avoid assigning two failover-capable lanes that collapse onto the same DC DCI, so lane failure domains stay independent.
  4. Do not simply relax the assert — it is catching a real invariant violation (a non-NOP WQE on a dead queue).

Related: PR #12126 (this change); context on failover lane rebuild: #11562, #11563, #11988, #12085; recent txwq FAILED/purge work: #11829, #12058.

🛡️ This comment had 1 potential secret(s) redacted (Hex High Entropy String). See request_id ff3e3bb4-a05f-4cb1-a733-8e8fba0bb87f in the triage console for the audit trail.

Comment thread src/ucs/sys/topo/base/topo.c Resolved
Comment thread src/ucs/sys/topo/base/topo.c Resolved
Comment thread test/gtest/ucs/test_topo.cc Resolved
Comment thread src/ucs/sys/topo/base/topo_int.h Resolved
Comment thread src/ucs/sys/topo/base/topo.c Resolved
@svc-nvidia-pr-review

Copy link
Copy Markdown

🤖 Starting review — findings will be posted here when done.

@tomerg-nvidia
tomerg-nvidia requested a review from tvegas1 October 27, 2026 10:36
Comment thread src/ucs/sys/topo/base/topo.c Resolved
Comment thread src/ucs/sys/topo/base/topo.c Resolved
@svc-ucx

svc-ucx commented Oct 27, 2026

Copy link
Copy Markdown

🤖 CI Triage Agent — UCX PR (Coverity coverity release on coverity_rh7) · commit 13342ad4

TL;DR: The Coverity release job failed on a single new OVERRUN defect: ucs_topo_sys_device_clear_siblings() iterates the 256-bit siblings bitmap and uses the bit index to index ucs_topo_global_ctx.devices[], which only has 255 entries — fix by bounding the loop index to num_devices (or sizing the devices array to the bitmap's 256-bit capacity).

Full analysis

Summary: coverity release on coverity_rh7 passed cov-build but cov-analyze reported 1 blocking issue (nerrors=1), causing ##[error]Coverity found 1 issues: /src/ucs/sys/topo/base/topo.c:1406 Type: Out-of-bounds read (OVERRUN).

Root cause: Size mismatch between the new sibling bitmap and the device table introduced by this PR:

  • src/ucs/sys/topo/base/topo.c:73 — ucs_topo_sys_device_info_t devices[UCS_SYS_DEVICE_ID_COUNT] = UINT8_MAX - 1 + 1 = 255 elements (valid indices 0–254).
  • src/ucs/sys/topo/base/topo_int.h:33 — ucs_sys_device_bitmap_t is ucs_static_bitmap_s(UCS_SYS_DEVICE_ID_COUNT); ucs_static_bitmap_s rounds up to whole words (ucs_div_round_up(255, 64) = 4 words), so the bitmap physically holds 256 bits.
  • UCS_STATIC_BITMAP_FOR_EACH_BIT (static_bitmap.h:387) iterates over the full word capacity (NUM_WORDS * 64 = 256 bits), so peer can reach 255.

At topo.c:1405-1407 that index is used directly as ucs_topo_global_ctx.devices[peer], i.e. a read one element past the end (Coverity: "Overrunning array ... of 255 96-byte elements at element index 255"). Note bit 255 is also exactly UCS_SYS_DEVICE_ID_UNKNOWN, so the loop has no guard that the set bit corresponds to a registered device, unlike every other accessor in this file which checks sys_dev < num_devices.

Implicated commit: 8e802529 "UCS/SYS/TOPO: Allow multiple sibling devices per memory device" (Tomer Gilad) — introduced the siblings bitmap and ucs_topo_sys_device_clear_siblings(); still present at HEAD 13342ad4 "UCS/SYS/TOPO: Fix CR comments" (Tomer Gilad).

File: src/ucs/sys/topo/base/topo.c:1400-1411 (defect reported at line 1406); related declarations at src/ucs/sys/topo/base/topo.c:73 and src/ucs/sys/topo/base/topo_int.h:33.

Suggested fix: Guard the loop body with the same validity check used elsewhere in the file:

static void ucs_topo_sys_device_clear_siblings(ucs_sys_device_t sys_dev)
{
    ucs_topo_sys_device_info_t *device = &ucs_topo_global_ctx.devices[sys_dev];
    unsigned peer;

    UCS_STATIC_BITMAP_FOR_EACH_BIT(peer, &device->siblings) {
        if (peer >= ucs_topo_global_ctx.num_devices) {
            /* Bits past the last registered device are never set; the bitmap
             * capacity is rounded up to a whole word, so bound the index. */
            break;
        }
        UCS_STATIC_BITMAP_RESET(&ucs_topo_global_ctx.devices[peer].siblings,
                                sys_dev);
    }

    UCS_STATIC_BITMAP_RESET_ALL(&device->siblings);
}

Alternatively (more structural, and it also makes UCS_SYS_DEVICE_ID_UNKNOWN a legal index): size the table to the full uint8_t range, e.g. devices[UCS_SYS_DEVICE_ID_COUNT + 1], so the array always covers the word-rounded bitmap capacity. Avoid fixing this with a /* coverity[overrun-local] */ suppression — the mismatch is real, not a false positive. Add a unit test that registers devices and calls ucs_topo_sys_device_set_sys_dev_aux() / ucs_topo_sys_device_enable_aux_path() twice to exercise the clear path.

Related: PR #12126 (the PR under test, "UCS/SYS/TOPO: Allow multiple sibling devices per memory device"); Coverity report published as build artifact coverity_release (cov_build_release/output/errors/index.html) for build 140891.

Comment thread src/ucs/sys/topo/base/topo.c Resolved
Comment thread test/gtest/ucs/test_topo.cc Resolved
Comment thread test/gtest/ucs/test_topo.cc Resolved
Comment thread test/gtest/ucs/test_topo_groups.cc Resolved
@svc-nvidia-pr-review

Copy link
Copy Markdown

🤖 Starting review — findings will be posted here when done.

*/
(ucs_topo_global_ctx.devices[sys_dev_mem].sibling_sys_dev ==
sys_dev);
UCS_STATIC_BITMAP_GET(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the siblings bitmap is symmetric now, so is_sibling(mem, dev) also returns true and then trips the assert below (and silently returns 1 in release builds). pls make the role part of the condition instead of only asserting it:
(devices[sys_dev].sibling_role == UCS_TOPO_SIBLING_ROLE_DEV) && UCS_STATIC_BITMAP_GET(...)

Swapped calls do exist in the tree (test_topo.cc sibling test calls ucs_topo_is_sibling(gpu_dev, hca_devs[0])), and the old scalar only exposed this for the one representative MEM, so the bitmap widens the exposure to every alias and plane.


UCS_STATIC_BITMAP_FOR_EACH_BIT(peer, &device->siblings) {
if (peer >= ucs_topo_global_ctx.num_devices) {
break;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor: bits are only set for indices < num_devices (every registration does RESET_ALL, and num_devices only grows except via extract_state, whose callers bound-check sys_dev), so this branch is unreachable. A silent break would also leave the remaining peers stale while device->siblings is cleared below, i.e. asymmetric state. Suggestion:

    UCS_STATIC_BITMAP_FOR_EACH_BIT(peer, &device->siblings) {
        ucs_assertv(peer < ucs_topo_global_ctx.num_devices,
                    "sys_dev=%u peer=%u num_devices=%u", sys_dev, peer,
                    ucs_topo_global_ctx.num_devices);
        UCS_STATIC_BITMAP_RESET(&ucs_topo_global_ctx.devices[peer].siblings,
                                sys_dev);
    }

UCS_TOPO_SIBLING_ROLE_MEM;

/* All devices sharing the auxiliary device match the memory device */
for (dev = 0; dev < ucs_topo_global_ctx.num_devices; dev++) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor: is_pci_bridge() does 2 realpath() + 3 PATH_MAX allocations per candidate under the global spinlock, so now every memory device pays it for all DEVs. With MPS aliases this becomes num_mems * num_devs path resolutions at init. maybe we can resolve the sysfs path of sys_dev_aux once per device instead of per pair?

@svc-nvidia-pr-review

Copy link
Copy Markdown

Residual coverage gap: still no test asserting the MEM-side bit is dropped from a specific plane (only device_has_sibling() aggregate checks), so a wrong-direction RESET in clear_siblings would not be caught.

Residual coverage gap: the new tests remain hardware dependent: num_planes + 1 HCAs, a GPU, a DMA engine, plus the assumption that m_hcas[num_planes] is not behind the GPU's bridge (guarded by UCS_TEST_SKIP_R, so CI may silently skip the negative assertions).

@svc-ucx

svc-ucx commented Oct 29, 2026

Copy link
Copy Markdown

🤖 CI Triage Agent — UCX PR (Coverity coverity release on coverity_rh7) · commit faef0d40

TL;DR: The Coverity release job failed because of one new OVERRUN defect: ucs_topo_sys_device_clear_siblings() iterates the 256-bit-wide (word-rounded) siblings static bitmap and indexes ucs_topo_global_ctx.devices[], which only has 255 entries — the existing peer >= num_devices guard uses a runtime variable Coverity can't bound. Replace/augment it with a compile-time bound (UCS_SYS_DEVICE_ID_COUNT).

Full analysis

Summary: cov-analyze reported 1 issue (nerrors=1) and the task aborted: Out-of-bounds read (OVERRUN) at src/ucs/sys/topo/base/topo.c:1410.

Root cause: ucs_sys_device_bitmap_t is declared as ucs_static_bitmap_s(UCS_SYS_DEVICE_ID_COUNT) (255 bits), but ucs_static_bitmap_s rounds up to whole 64-bit words → 4 words = 256 addressable bits. UCS_STATIC_BITMAP_FOR_EACH_BIT iterates over whole words, so peer can reach 255, while ucs_topo_global_ctx.devices[] is [UCS_SYS_DEVICE_ID_COUNT] = 255 elements (valid indices 0–254; 255 is UCS_SYS_DEVICE_ID_UNKNOWN). The loop's only guard is if (peer >= ucs_topo_global_ctx.num_devices) break; — num_devices is an unsigned global that Coverity cannot prove is ≤ 255, so it concludes peer == 255 reaches devices[255] (the log shows exactly this path: "Overrunning array ... of 255 96-byte elements at element index 255"). Commit c1658508 ("Bound sibling index in clear_siblings") was clearly an attempt to fix this, but a variable bound doesn't satisfy the checker (and the padding bits are genuinely reachable by the iterator).

Implicated commit: 8e802529 "UCS/SYS/TOPO: Allow multiple sibling devices per memory device" (Tomer Gilad) — introduced the siblings bitmap and this loop; follow-up c1658508 (Tomer Gilad) attempted the bound but left it variable-based.

File: src/ucs/sys/topo/base/topo.c:1405-1412 (bitmap type at src/ucs/sys/topo/base/topo_int.h:33, word rounding at src/ucs/datastruct/static_bitmap.h:24-28)

Suggested fix: Make the bound a compile-time constant so the array index is provably in range, e.g.:

UCS_STATIC_BITMAP_FOR_EACH_BIT(peer, &device->siblings) {
    if ((peer >= UCS_SYS_DEVICE_ID_COUNT) ||
        (peer >= ucs_topo_global_ctx.num_devices)) {
        break;
    }

    UCS_STATIC_BITMAP_RESET(&ucs_topo_global_ctx.devices[peer].siblings,
                            sys_dev);
}

(plus ucs_assertv(ucs_topo_global_ctx.num_devices <= UCS_SYS_DEVICE_ID_COUNT, ...)). Alternatively, eliminate the padding-bit gap entirely by sizing the bitmap to the word-rounded device count, or by masking the tail bits (UCS_STATIC_BITMAP_MASK) after any SET, so no reachable bit index can exceed the array bounds.

Related: PR #12126 (the PR under test) — #12126

The siblings bitmap is rounded up to a whole word, so its iterator can
yield an index past the devices table. num_devices is a runtime value
Coverity cannot bound, so also check against UCS_SYS_DEVICE_ID_COUNT.
@svc-nvidia-pr-review

Copy link
Copy Markdown

🤖 Starting review — findings will be posted here when done.

Comment thread src/ucs/sys/topo/base/topo.c Resolved
Comment thread test/gtest/ucs/test_topo.cc Resolved
Comment thread test/gtest/ucs/test_topo_groups.cc Resolved

@tvegas1 tvegas1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor

* the MEM-side sibling is the canonical relationship.
* The MEM side holds every matched DEV, including all planes
* of a multiplane NIC.
*/

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The bitmap is symmetric, so swapped arguments also return true and trip the assert. Please gate on the role, like ucs_topo_is_reachable() does.

Suggested change
*/
(ucs_topo_global_ctx.devices[sys_dev].sibling_role ==
UCS_TOPO_SIBLING_ROLE_DEV) &&
/*
* The MEM side holds every matched DEV, including all planes
* of a multiplane NIC.
*/
UCS_STATIC_BITMAP_GET(
ucs_topo_global_ctx.devices[sys_dev_mem].siblings,
sys_dev);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

The siblings bitmap is symmetric, so with swapped arguments the DEV side
bit matched as well and tripped the role assertion.
@svc-nvidia-pr-review

Copy link
Copy Markdown

🤖 Starting review — findings will be posted here when done.

@tvegas1
tvegas1 enabled auto-merge (squash) October 29, 2026 13:23
unsigned peer;

UCS_STATIC_BITMAP_FOR_EACH_BIT(peer, &device->siblings) {
if ((peer >= UCS_SYS_DEVICE_ID_COUNT) ||

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor: a sibling bit is only ever set for a registered device (both ids in sibling_match() are < num_devices), so this can never trigger; pls make it an assert instead of silently skipping the rest of the peers.

Suggested change
if ((peer >= UCS_SYS_DEVICE_ID_COUNT) ||
ucs_assertv(peer < ucs_topo_global_ctx.num_devices,
"peer=%u num_devices=%u", peer,
ucs_topo_global_ctx.num_devices);

(sys_dev_mem != UCS_SYS_DEVICE_ID_UNKNOWN) &&
(sys_dev_mem < ucs_topo_global_ctx.num_devices) &&
(ucs_topo_global_ctx.devices[sys_dev].sibling_role ==
UCS_TOPO_SIBLING_ROLE_DEV) &&

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor: with this check in the condition, role_dev == UCS_TOPO_SIBLING_ROLE_DEV in the assert below is always true - pls assert only role_dev_mem.


// Setting the same auxiliary device again keeps the pairing
ASSERT_UCS_OK(ucs_topo_sys_device_set_sys_dev_aux(plane, dma_dev));
EXPECT_TRUE(ucs_topo_is_sibling(plane, gpu_dev));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we also call ucs_topo_sys_device_enable_aux_path(gpu_dev) twice here? The new MEM early-return in enable_aux_path() is not covered, while the set_sys_dev_aux() one is covered by this check.

@svc-nvidia-pr-review

Copy link
Copy Markdown

Residual gaps (not posted, already raised in earlier rounds): the suite still depends on the host having num_planes + 1 HCAs plus a GPU/DMA pair behind a common bridge, and on m_hcas[last] not sharing the GPU bridge, so CI can skip the negative assertions silently.

@svc-ucx

svc-ucx commented Oct 30, 2026

Copy link
Copy Markdown

🤖 CI Triage Agent — UCX PR · commit 548e94fc

Summary: Unable to fetch logs — cannot diagnose without them.
Root cause: Unknown — log access failed.
Implicated commit: unknown
File: unknown
Suggested fix: Provide a direct link to the failed build log in a follow-up comment.
Log fetch attempts:

  • fetch_azure_logs({'build_url': 'https://dev.azure.com/ucfconsort/0b36e3f0-8ab9-4a48-b68b-[REDACTED:Hex High Entropy String]/_build/results?buildId=141593'}) → [fetch_azure_logs ERROR: no failed job found in timeline for build 141593]
  • fetch_jenkins_stages({'job': 'UCX PR', 'build': 141593}) → [fetch_jenkins_stages ERROR] build URL names Jenkins controller 'https://dev.azure.com/ucfconsort/0b36e3f0-8ab9-4a48-b68b-[REDACTED:Hex High Entropy String]/_build/results?buildId=141593', but this deployment is configured for 'https://nbuprod.blsm.nvidia.com/nb
  • fetch_jenkins_logs({'job': 'UCX PR', 'build': 141593}) → [fetch_jenkins_logs ERROR] build URL names Jenkins controller 'https://dev.azure.com/ucfconsort/0b36e3f0-8ab9-4a48-b68b-[REDACTED:Hex High Entropy String]/_build/results?buildId=141593', but this deployment is configured for 'https://nbuprod.blsm.nvidia.com/nbu-
  • fetch_azure_logs({'build_url': 'https://dev.azure.com/ucfconsort/ucx/_build/results?buildId=141593'}) → [fetch_azure_logs ERROR: no failed job found in timeline for build 141593]

🛡️ This comment had 1 potential secret(s) redacted (Hex High Entropy String). See request_id 5ef1a7b7-f653-42bf-bc0f-42bdaa042ec4 in the triage console for the audit trail.

@tvegas1
tvegas1 merged commit f21cfca into openucx:master Oct 30, 2026
167 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants