diff options
| author | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-11 21:08:05 -0400 |
|---|---|---|
| committer | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-11 21:08:05 -0400 |
| commit | d2c9054b096e63ca3dd4f890514639f7efd82c3f (patch) | |
| tree | 14cacf558e6ce39675f6d5f8f516d833043f2e14 /tools/guest-diag/guest_pin_stream.py | |
| parent | 66d7e5f93ed0f3139ba4a6635bf355a4c0052a04 (diff) | |
| download | open-iov-d2c9054b096e63ca3dd4f890514639f7efd82c3f.tar.gz open-iov-d2c9054b096e63ca3dd4f890514639f7efd82c3f.zip | |
guest-diag: scanner detects arbitrary CUDA clients by nvidia fds
The guest pin scanner only tracked processes whose comm matched
CLIENT_PREFIXES (cdt,va,victory). An arbitrary CUDA binary (e.g.
/tmp/smiley) was invisible: no pages streamed, no VA->PA pins injected,
the service could not read its pushes and the client hung in
cudaMalloc/uvm_tracker_wait. Detect compute clients by the CUDA device
they hold open (/dev/nvidia-uvm preferred, then any /dev/nvidia*), with
the prefix match kept as the first-choice path.
Diffstat (limited to 'tools/guest-diag/guest_pin_stream.py')
| -rw-r--r-- | tools/guest-diag/guest_pin_stream.py | 48 |
1 files changed, 44 insertions, 4 deletions
diff --git a/tools/guest-diag/guest_pin_stream.py b/tools/guest-diag/guest_pin_stream.py index 031271c..29ef114 100644 --- a/tools/guest-diag/guest_pin_stream.py +++ b/tools/guest-diag/guest_pin_stream.py @@ -632,18 +632,42 @@ def new_sems(seen): return found +def nvidia_fds(pid): + """CUDA device fds this pid holds: 'uvm', 'gpu', or None. + + /dev/nvidia-uvm marks a compute client (the CUDA runtime opens it at + context init; nvidia-smi and persistenced do not), so a process holding + it is a real client regardless of its binary name. + """ + kind = None + try: + fddir = '/proc/%s/fd' % pid + for fd in os.listdir(fddir): + try: + tgt = os.readlink(os.path.join(fddir, fd)) + except OSError: + continue + if tgt.startswith('/dev/nvidia-uvm'): + return 'uvm' + if tgt.startswith('/dev/nvidia'): + kind = 'gpu' + except OSError: + pass + return kind + + def cdt_pid(): prefixes = tuple(p for p in os.environ.get("CLIENT_PREFIXES", "cdt,va,victory").split(",") if p) best = None + uvm = None + gpu = None for d in os.listdir('/proc'): if not d.isdigit(): continue try: with open('/proc/%s/comm' % d) as f: name = f.read().strip() - if not any(name.startswith(p) for p in prefixes): - continue # Skip zombies: a defunct previous client keeps its comm and # would otherwise shadow the live client (pagemap reads then fail # and no pins are ever streamed). @@ -652,10 +676,26 @@ def cdt_pid(): rp = st.rfind(')') if rp >= 0 and st[rp + 2:rp + 3] == 'Z': continue - best = int(d) + if any(name.startswith(p) for p in prefixes): + best = int(d) + continue + # Arbitrary CUDA binaries (any comm) are clients too: match by + # the CUDA device they hold open so streaming never depends on + # the binary's name. Prefer a UVM holder (compute client) over a + # plain /dev/nvidia0 holder (nvidia-smi, persistenced); the last + # match wins, which is the newest client when several overlap. + kind = nvidia_fds(d) + if kind == 'uvm': + uvm = int(d) + elif kind == 'gpu': + gpu = int(d) except OSError: pass - return best + if best is not None: + return best + if uvm is not None: + return uvm + return gpu def scan_window(fd, lo, hi, span, out): |
