summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-12 11:51:32 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-12 11:51:32 -0400
commit9521339338f096d76fe22c3496ff435a48dffba9 (patch)
tree2bf9d7e03431c6049fb1a94b71855f67e2ef7268
parent70a80cc733f94b7bd27ec2e61173e39221c22324 (diff)
downloadopen-iov-9521339338f096d76fe22c3496ff435a48dffba9.tar.gz
open-iov-9521339338f096d76fe22c3496ff435a48dffba9.zip
guest-diag: stream the newest client and seed the CE chain from uvch
Two robustness fixes for the sequential client battery. cdt_pid() now picks the highest-pid CUDA candidate: preferring a name-prefix match kept the scanner pinned to a previous client that was still tearing down while the new client had already started pushing, so its first pushes were unreadable, the release expectation drifted past the real payloads and the stall followed. The CE push-buffer chain resolver now also runs for uvch channel kptrs, so the pins do not depend on the uvmt semaphore events alone.
-rw-r--r--tools/guest-diag/guest_pin_stream.py50
1 files changed, 32 insertions, 18 deletions
diff --git a/tools/guest-diag/guest_pin_stream.py b/tools/guest-diag/guest_pin_stream.py
index a33a183..35cbfb9 100644
--- a/tools/guest-diag/guest_pin_stream.py
+++ b/tools/guest-diag/guest_pin_stream.py
@@ -755,9 +755,7 @@ def cdt_pid():
# scanner must never commit to them (a transient nvidia-smi at boot was
# picked once and its exited pagemap read back EOF forever).
non_clients = ("nvidia-smi", "nvidia-persistenced", "Xorg", "X")
- best = None
- uvm = None
- gpu = None
+ cands = []
for d in os.listdir('/proc'):
if not d.isdigit():
continue
@@ -772,28 +770,24 @@ def cdt_pid():
rp = st.rfind(')')
if rp >= 0 and st[rp + 2:rp + 3] == 'Z':
continue
- if any(name.startswith(p) for p in prefixes):
- best = int(d)
- continue
if any(name.startswith(p) for p in non_clients):
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.
+ # the binary's name. The newest candidate (highest pid) is the
+ # client being streamed: preferring a name-prefix match first
+ # pinned the scanner to a previous client that was still tearing
+ # down while the new client had already started pushing (its
+ # first pushes were unreadable, the expectation drifted, and the
+ # stall followed).
kind = nvidia_fds(d)
- if kind == 'uvm':
- uvm = int(d)
- elif kind == 'gpu':
- gpu = int(d)
+ if kind is not None or any(name.startswith(p) for p in prefixes):
+ cands.append(int(d))
except OSError:
pass
- if best is not None:
- return best
- if uvm is not None:
- return uvm
- return gpu
+ if not cands:
+ return None
+ return max(cands)
def scan_window(fd, lo, hi, span, out):
@@ -1131,6 +1125,26 @@ def main():
added += len(got)
else:
retry_at[ch] = now_r + 1.0
+ # A uvch channel kptr is another early seed for the CE
+ # push-buffer chain (its window contains the pool pointer):
+ # resolve it here so the pins never depend on the uvmt sem
+ # events alone.
+ if ch in resolved_kc_pb or \
+ now_r < retry_at.get(("pk", ch), 0):
+ continue
+ got = []
+ try:
+ _found = resolve_pb_chain(kc, ch, got)
+ except Exception:
+ _found = False
+ got = []
+ if _found:
+ resolved_kc_pb.add(ch)
+ if got:
+ lines.extend(got)
+ added += len(got)
+ else:
+ retry_at[("pk", ch)] = now_r + 2.0
if added:
try:
with open('/tmp/guest_pin_stream.log', 'a') as f: