Skip to content

Commit 556410b

Browse files
committed
Add crs_eviction detector
Orabug: 38559518 Signed-off-by: Richard Li <[email protected]>
1 parent 58cfc66 commit 556410b

File tree

2 files changed

+93
-0
lines changed

2 files changed

+93
-0
lines changed

drgn_tools/crs_eviction.py

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# Copyright (c) 2025, Oracle and/or its affiliates.
2+
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
3+
"""
4+
Help detect crs eviction issues
5+
"""
6+
import argparse
7+
from typing import Optional
8+
9+
import drgn
10+
from drgn import ObjectAbsentError
11+
from drgn import Program
12+
from drgn.helpers.linux.sched import cpu_curr
13+
14+
from drgn_tools.corelens import CorelensModule
15+
from drgn_tools.dentry import dentry_for_each_child
16+
from drgn_tools.dentry import dentry_is_negative
17+
from drgn_tools.file import __path_by_inode
18+
from drgn_tools.lockup import tasks_waiting_fsnotify
19+
from drgn_tools.lockup import tasks_waiting_rcu_gp
20+
from drgn_tools.lockup import tasks_waiting_spinlock
21+
from drgn_tools.task import get_pid
22+
23+
24+
def crs_eviction_waiting_for_rcu(prog: Program) -> None:
25+
"""Different types of issues related to rcu"""
26+
if not tasks_waiting_rcu_gp(prog):
27+
return
28+
29+
# spinlock contention issue
30+
if tasks_waiting_spinlock(prog):
31+
# due to fsnotify
32+
frame_list = tasks_waiting_fsnotify(prog)
33+
if frame_list:
34+
for task, frame in frame_list:
35+
if frame.name == "__fsnotify_update_child_dentry_flags":
36+
if "alias" in frame.locals():
37+
dentry = frame["alias"]
38+
try:
39+
path_name = __path_by_inode(dentry.d_inode)
40+
total_count = 0
41+
negative_count = 0
42+
for child in dentry_for_each_child(dentry):
43+
total_count += 1
44+
if dentry_is_negative(child):
45+
negative_count += 1
46+
except ObjectAbsentError:
47+
continue
48+
49+
print(
50+
"CRS eviction caused by spinlock contention due to fsnotify detected."
51+
)
52+
print(f"PID: {get_pid(task)}")
53+
print(f"Directory being iterated: {path_name}")
54+
print(f"Total dentries: {total_count}")
55+
print(f"Negative dentries: {negative_count}")
56+
if total_count:
57+
print(
58+
f"% Negative dentries: {negative_count / total_count:.2%}"
59+
)
60+
61+
62+
def panic_triggered_by_crs_eviction(prog: Program) -> Optional[drgn.Thread]:
63+
# dectect panic triggered by crs eviction
64+
try:
65+
panic_thread = prog.crashed_thread()
66+
except Exception:
67+
pid = cpu_curr(prog, prog["crashing_cpu"]).pid.value_()
68+
panic_thread = prog.thread(pid)
69+
if panic_thread and panic_thread.name in {"cssdmonitor", "ocssd.bin"}:
70+
return panic_thread
71+
return None
72+
73+
74+
def scan_crs_eviction(prog: Program) -> None:
75+
if panic_triggered_by_crs_eviction(prog):
76+
# run a list of detectors
77+
crs_eviction_waiting_for_rcu(prog)
78+
79+
80+
class CrsEviction(CorelensModule):
81+
"""Detectors for crs eviction related issues"""
82+
83+
name = "crs_eviction"
84+
85+
def run(self, prog: Program, args: argparse.Namespace) -> None:
86+
scan_crs_eviction(prog)

tests/test_crs_eviction.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Copyright (c) 2025, Oracle and/or its affiliates.
2+
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
3+
from drgn_tools import crs_eviction
4+
5+
6+
def test_crs_eviction(prog):
7+
crs_eviction.scan_crs_eviction(prog)

0 commit comments

Comments
 (0)