diff options
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/guest-diag/pin_gr_stream.py | 22 | ||||
| -rwxr-xr-x | tools/guest-diag/semfix_uvmt.py | 10 |
2 files changed, 29 insertions, 3 deletions
diff --git a/tools/guest-diag/pin_gr_stream.py b/tools/guest-diag/pin_gr_stream.py index 2f78f2a..6ba51ee 100644 --- a/tools/guest-diag/pin_gr_stream.py +++ b/tools/guest-diag/pin_gr_stream.py @@ -328,10 +328,11 @@ def main(): chunk = conn.recv(1 << 20) except socket.timeout: if runs: + novel = _novel_pages(runs, seen) pages = _flush(runs, seen) pin_total += pages pins_since_client += pages - if pages: + if novel: _activity() runs = [] _maybe_reassert_request(seen) @@ -433,12 +434,18 @@ def main(): int(m.group(2), 16), int(m.group(3)) if m.group(3) else 1)) if runs: + novel = _novel_pages(runs, seen) pages = _flush(runs, seen) pin_total += pages pins_since_client += pages - if pages: + if novel: _activity() runs = [] + # Poll the semfix re-assert request on every recv cycle, not + # only on recv-timeouts: sustained scanner traffic starves the + # timeout branch, so the request fired post-mortem in r203 + # (119 s late, `seen` already cleared by #nopid). + _maybe_reassert_request(seen) except Exception as e: # A transient error on one connection must not kill the process: # log it, drop the connection and go back to accept(). @@ -482,6 +489,17 @@ def _coalesce_seen(seen): return runs +def _novel_pages(runs, seen): + """Count pages in runs whose translation is new or changed. + + Progress accounting for the stall watchdog: the guest re-streams the CE + window and UVM pool every couple of seconds even when nothing moves, so a + pure repeat of an already-known pair must not count as pin activity + (r203: those repeats masked the watchdog through every hang).""" + return sum(1 for va, pa, n in runs for i in range(n) + if seen.get(va + i * 0x1000) != pa + i * 0x1000) + + def _flush(runs, seen, full=False): """Inject run lines (one batched sudo pass), return number of pages pinned. diff --git a/tools/guest-diag/semfix_uvmt.py b/tools/guest-diag/semfix_uvmt.py index f28efd3..11c191c 100755 --- a/tools/guest-diag/semfix_uvmt.py +++ b/tools/guest-diag/semfix_uvmt.py @@ -671,7 +671,12 @@ def main(): for sem in sorted(sems - known_sems): known_sems.add(sem) - for sem in sorted(known_sems): + for hb_i, sem in enumerate(sorted(known_sems)): + if hb_i % 16 == 0: + # A full pass can run 60-90 s (thousands of QMP reads); keep + # the heartbeat fresh inside it (r203: 79 s gap -> supervisor + # restarted the tool mid-pass). + _hb() now = time.time() if now < skip_until.get(sem, 0): continue @@ -793,6 +798,7 @@ def main(): qmp_next_try = now + 5.0 for ch in sorted(chans - seen_ch): + _hb() # a resolve can block for tens of seconds d = {} try: res = resolve_from_channel(q, ch, d) @@ -807,6 +813,7 @@ def main(): else: log("semfix: ch=0x%x pushbuf miss [%s]" % (ch, diag_str(d))) for pb in sorted(pbs - seen_pb): + _hb() # a resolve can block for tens of seconds d = {} try: res = resolve_from_pushbuffer(q, pb, d) @@ -833,6 +840,7 @@ def main(): if loop % 8 == 0: for st in list(pinned_ranges.values()): if not st["done"] and st["tries"] > 0: + _hb() # pin_range_once can walk thousands of QMP reads pin_range_once(*st["args"]) # Dead-pid detection and the pre-capture stall watchdog. The guest is |
