Skip to content

fix(monitor): clamp SetDeviceSmLimit and SetDeviceMemoryLimit to maxDevices - #2362

Merged
hami-robot[bot] merged 1 commit into
Project-HAMi:masterfrom
Nakshatra480:fix/clamp-device-limit-setter-index
Aug 6, 2026
Merged

fix(monitor): clamp SetDeviceSmLimit and SetDeviceMemoryLimit to maxDevices#2362
hami-robot[bot] merged 1 commit into
Project-HAMi:masterfrom
Nakshatra480:fix/clamp-device-limit-setter-index

Conversation

@Nakshatra480

@Nakshatra480 Nakshatra480 commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Summary

SetDeviceSmLimit and SetDeviceMemoryLimit in both pkg/monitor/nvidia/v0/spec.go and pkg/monitor/nvidia/v1/spec.go iterated up to sr.num without clamping to the backing array size. sr.limit and sr.smLimit are both [16]uint64, matching maxDevices = 16. If sr.num comes in larger than 16 - due to shared-memory corruption or a version mismatch between libvgpu and the monitor, the write panics with an index out of bounds, bringing down the vGPU monitor and silencing all GPU metrics on that node.

The fix caps the loop to min(sr.num, maxDevices) in all four setters across v0 and v1, matching the same guard already applied to sr.procnum in activeProcs() (introduced in #2282).

Files changed:

  • pkg/monitor/nvidia/v0/spec.go: SetDeviceSmLimit, SetDeviceMemoryLimit
  • pkg/monitor/nvidia/v1/spec.go: SetDeviceSmLimit, SetDeviceMemoryLimit
  • pkg/monitor/nvidia/v0/spec_test.go: added "num larger than maxDevices does not panic" regression case to both setter tests
  • pkg/monitor/nvidia/v1/spec_test.go: same

Which issue(s) this PR fixes:
Part of #2126 (LFX observability hardening - vGPU monitor stability)

Special notes for your reviewer:
sr.num is written by libvgpu at shared-memory initialisation and is read directly from the mmap'd region. It should always be ≤ 16, but the same assumption was made about sr.procnum before #2282. This applies the identical guard to the remaining unclamped loops for consistency and to prevent the monitor from going down on corrupt input.

Does this PR introduce a user-facing change?
Yes - the vGPU monitor no longer panics if sr.num exceeds maxDevices, so all GPU metrics stay available instead of going dark.

Summary by CodeRabbit

Bug Fixes

  • Prevented errors when configuring shared-memory or memory limits for oversized device configurations.
  • Ensured all supported device slots receive the appropriate limits across NVIDIA monitoring versions.

Tests

  • Added regression coverage confirming oversized device counts are handled safely without crashes.

AI Disclosure:
AI assistance was used for code inspection and draft formatting. Changes and tests were manually validated.

@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 38eddddb-39d8-4af6-8e02-5530a840f3b7

📥 Commits

Reviewing files that changed from the base of the PR and between da47cef and 4b48c18.

📒 Files selected for processing (4)
  • pkg/monitor/nvidia/v0/spec.go
  • pkg/monitor/nvidia/v0/spec_test.go
  • pkg/monitor/nvidia/v1/spec.go
  • pkg/monitor/nvidia/v1/spec_test.go
🚧 Files skipped from review as they are similar to previous changes (4)
  • pkg/monitor/nvidia/v1/spec_test.go
  • pkg/monitor/nvidia/v1/spec.go
  • pkg/monitor/nvidia/v0/spec_test.go
  • pkg/monitor/nvidia/v0/spec.go

📝 Walkthrough

Walkthrough

The NVIDIA v0 and v1 device-limit setters now cap iteration at maxDevices. Regression tests cover oversized device counts for shared-memory and memory limits.

Changes

NVIDIA device-limit bounds

Layer / File(s) Summary
Bound per-device limit updates
pkg/monitor/nvidia/v0/spec.go, pkg/monitor/nvidia/v1/spec.go
Both versions cap SetDeviceSmLimit and SetDeviceMemoryLimit updates at maxDevices.
Validate oversized device counts
pkg/monitor/nvidia/v0/spec_test.go, pkg/monitor/nvidia/v1/spec_test.go
Tests verify that oversized device counts fill all 16 available entries without panicking. The v0 memory-limit expectation uses a single-line slice literal.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

Suggested reviewers: mesutoezdil

Poem

A rabbit counts the slots in line,
Sixteen entries fit just fine.
Shared and memory limits stay in bounds,
No panic leaps beyond the grounds.
The arrays rest, safe and sound. 🐇

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main fix: clamping both setters to maxDevices.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pkg/monitor/nvidia/v1/spec_test.go`:
- Around line 743-749: Replace the invalid assert.DeepEqual call in the “num
larger than maxDevices does not panic” test with assert.Equal, matching the
gotest.tools/v3/assert API already imported by the file. Apply the same
correction to the other referenced assertion calls in this test file.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 955cbbff-40e6-4423-b341-10a8af13be11

📥 Commits

Reviewing files that changed from the base of the PR and between 2cabe29 and 47a8a29.

📒 Files selected for processing (4)
  • pkg/monitor/nvidia/v0/spec.go
  • pkg/monitor/nvidia/v0/spec_test.go
  • pkg/monitor/nvidia/v1/spec.go
  • pkg/monitor/nvidia/v1/spec_test.go

Comment thread pkg/monitor/nvidia/v1/spec_test.go
@github-actions github-actions Bot added the kind/bug Something isn't working label Aug 4, 2026
@SK8-infi

SK8-infi commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

@Nakshatra480 heads up, reviewers also require an AI disclosure. you can refer https://github.com/Project-HAMi/HAMi/blob/master/CONTRIBUTING.md

@Nakshatra480

Copy link
Copy Markdown
Contributor Author

I have updated the PR description to include the AI disclosure.

…evices

Both v0 and v1 setter loops used sr.num as the upper bound without
clamping to the backing array size. A corrupt or unexpectedly large
num field from shared memory would cause an index out-of-bounds panic,
bringing down the vGPU monitor and silencing all GPU metrics.

Cap the loop to min(sr.num, maxDevices) in all four setters, matching
the same guard already applied to sr.procnum in activeProcs.

Signed-off-by: Nakshatra Sharma <nakshatra.sharma3012@gmail.com>
@Nakshatra480
Nakshatra480 force-pushed the fix/clamp-device-limit-setter-index branch from 47a8a29 to 4b48c18 Compare August 6, 2026 06:21
@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@coderabbitai coderabbitai Bot removed the enhancement label Aug 6, 2026

@archlitchi archlitchi left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

/lgtm

@hami-robot

hami-robot Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: archlitchi, Nakshatra480

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@hami-robot hami-robot Bot added the approved label Aug 6, 2026
@codecov

codecov Bot commented Aug 6, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

Flag Coverage Δ
unittests 61.96% <100.00%> (+0.95%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
pkg/monitor/nvidia/v0/spec.go 95.45% <100.00%> (-0.14%) ⬇️
pkg/monitor/nvidia/v1/spec.go 100.00% <100.00%> (ø)

... and 14 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@hami-robot
hami-robot Bot merged commit c8969b7 into Project-HAMi:master Aug 6, 2026
17 checks passed
@Nakshatra480

Copy link
Copy Markdown
Contributor Author

@archlitchi Thanks of merging ☺️

om7057 added a commit to om7057/HAMi that referenced this pull request Aug 10, 2026
…Limit

mesutoezdil caught this on Project-HAMi#2179: master's merge into this branch
resolved a conflict between this branch's atomic conversion and Project-HAMi#2362
(merged on master, fixing a real scrape panic) by keeping only this
branch's side, silently dropping Project-HAMi#2362's min(s.sr.num, maxDevices)
clamp in both v0/spec.go and v1/spec.go.

limit/smLimit are fixed [16]uint64 arrays, but the loop bound came
straight from s.sr.num, an untrusted shared-memory field. Without the
clamp, a num greater than 16 indexes past the array and panics, which
is exactly what Project-HAMi#2362 fixed on master; the merge just needed both
changes combined, not one replacing the other.

Restored the clamp alongside the atomic stores this branch adds, and
brought over Project-HAMi#2362's "num larger than maxDevices does not panic"
subtests for both setters in v0 and v1, which the same conflict
resolution had dropped along with the fix.

Signed-off-by: Om Kulkarni <kulkarniom7057@gmail.com>
om7057 added a commit to om7057/HAMi that referenced this pull request Aug 18, 2026
…Limit

mesutoezdil caught this on Project-HAMi#2179: master's merge into this branch
resolved a conflict between this branch's atomic conversion and Project-HAMi#2362
(merged on master, fixing a real scrape panic) by keeping only this
branch's side, silently dropping Project-HAMi#2362's min(s.sr.num, maxDevices)
clamp in both v0/spec.go and v1/spec.go.

limit/smLimit are fixed [16]uint64 arrays, but the loop bound came
straight from s.sr.num, an untrusted shared-memory field. Without the
clamp, a num greater than 16 indexes past the array and panics, which
is exactly what Project-HAMi#2362 fixed on master; the merge just needed both
changes combined, not one replacing the other.

Restored the clamp alongside the atomic stores this branch adds, and
brought over Project-HAMi#2362's "num larger than maxDevices does not panic"
subtests for both setters in v0 and v1, which the same conflict
resolution had dropped along with the fix.

Signed-off-by: Om Kulkarni <kulkarniom7057@gmail.com>
om7057 added a commit to om7057/HAMi that referenced this pull request Aug 19, 2026
…Limit

mesutoezdil caught this on Project-HAMi#2179: master's merge into this branch
resolved a conflict between this branch's atomic conversion and Project-HAMi#2362
(merged on master, fixing a real scrape panic) by keeping only this
branch's side, silently dropping Project-HAMi#2362's min(s.sr.num, maxDevices)
clamp in both v0/spec.go and v1/spec.go.

limit/smLimit are fixed [16]uint64 arrays, but the loop bound came
straight from s.sr.num, an untrusted shared-memory field. Without the
clamp, a num greater than 16 indexes past the array and panics, which
is exactly what Project-HAMi#2362 fixed on master; the merge just needed both
changes combined, not one replacing the other.

Restored the clamp alongside the atomic stores this branch adds, and
brought over Project-HAMi#2362's "num larger than maxDevices does not panic"
subtests for both setters in v0 and v1, which the same conflict
resolution had dropped along with the fix.

Signed-off-by: Om Kulkarni <kulkarniom7057@gmail.com>
Signed-off-by: om7057 <kulkarniom7057@gmail.com>
hami-robot Bot pushed a commit that referenced this pull request Aug 21, 2026
* fix: use atomic load/store for shared-region limit fields

DeviceMemoryLimit, SetDeviceMemoryLimit and SetDeviceSmLimit in
pkg/monitor/nvidia/{v0,v1} read and write limit/smLimit in
sharedRegionT with plain Go assignments. These are the same
shared-memory words HAMi-core's shared_region_t.limit/sm_limit map
onto, and the C side already guarantees every other field in that
struct is atomic (see the companion fix in
Project-HAMi/HAMi-core#238). These two were the only fields left as
plain reads/writes on either side.

Switches all three methods to sync/atomic.LoadUint64/StoreUint64 on
the same words. No change to sharedRegionT's field types or layout,
so the wire format is unaffected. Existing unit tests in
pkg/monitor/nvidia/{v0,v1} pass unmodified under -race.

Signed-off-by: Om Kulkarni <kulkarniom7057@gmail.com>

* fix: read the shared num field once per Set call, not per iteration

SetDeviceSmLimit and SetDeviceMemoryLimit atomically store into
smLimit[idx]/limit[idx], but the loop condition re-read s.sr.num on
every iteration, so the store was atomic while its own loop bound was
not. Read s.sr.num once into a local before the loop in both v0 and
v1, so the whole function touches the shared region exactly once for
the count and atomically per element for the limit itself.

num/device_num is not declared _Atomic on the C side (it is written
once at shared-region creation and never changes afterward), so this
isn't adding a new atomic guarantee there was never a matching one to
add; it just stops re-reading the same shared word on every loop tick.

Signed-off-by: Om Kulkarni <kulkarniom7057@gmail.com>

* fix: extend atomic access to recentKernel, utilizationSwitch, lastKernelTime

Folds the remaining shared-region fields from PR #2180 into this
branch, so the atomic-access fix covers all fields the C side declares
_Atomic, not just limit/smLimit.

GetRecentKernel/SetRecentKernel and GetUtilizationSwitch/
SetUtilizationSwitch now use atomic.LoadInt32/StoreInt32 in both
v0/spec.go and v1/spec.go. LastKernelTime in v1/spec.go now uses
atomic.LoadInt64 (v0 has no lastKernelTime field on the C side and
always returns 0, so it's left as is).

Added TestSpec_ConcurrentAtomicAccess (v0) and Test_ConcurrentAtomicAccess
(v1), each running 50 goroutines x 200 iterations against a shared
sharedRegionT to exercise the setters/getters concurrently under
-race.

Co-authored-by: shivv23 <shivamkumar0423@gmail.com>
Signed-off-by: Om Kulkarni <kulkarniom7057@gmail.com>
Signed-off-by: om7057 <kulkarniom7057@gmail.com>

* fix: restore the maxDevices clamp on SetDeviceSmLimit/SetDeviceMemoryLimit

mesutoezdil caught this on #2179: master's merge into this branch
resolved a conflict between this branch's atomic conversion and #2362
(merged on master, fixing a real scrape panic) by keeping only this
branch's side, silently dropping #2362's min(s.sr.num, maxDevices)
clamp in both v0/spec.go and v1/spec.go.

limit/smLimit are fixed [16]uint64 arrays, but the loop bound came
straight from s.sr.num, an untrusted shared-memory field. Without the
clamp, a num greater than 16 indexes past the array and panics, which
is exactly what #2362 fixed on master; the merge just needed both
changes combined, not one replacing the other.

Restored the clamp alongside the atomic stores this branch adds, and
brought over #2362's "num larger than maxDevices does not panic"
subtests for both setters in v0 and v1, which the same conflict
resolution had dropped along with the fix.

Signed-off-by: Om Kulkarni <kulkarniom7057@gmail.com>
Signed-off-by: om7057 <kulkarniom7057@gmail.com>

* fix: use range-over-int in the concurrent atomic access tests

golangci-lint's modernize check flagged the classic for i := 0; i < n;
i++ loops in TestSpec_ConcurrentAtomicAccess (v0) and
Test_ConcurrentAtomicAccess (v1) as convertible to range-over-int.
Converted both the outer goroutine-spawning loop and the inner
iteration loop in each, since the linter caught one of each pair and
the other was the same pattern.

Signed-off-by: Om Kulkarni <kulkarniom7057@gmail.com>
Signed-off-by: om7057 <kulkarniom7057@gmail.com>

---------

Signed-off-by: Om Kulkarni <kulkarniom7057@gmail.com>
Signed-off-by: om7057 <kulkarniom7057@gmail.com>
Co-authored-by: shivv23 <shivamkumar0423@gmail.com>
Co-authored-by: limengxuan <mengxuan.li@dynamia.ai>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants