Skip to content

Commit 595472e

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

File tree

2 files changed

+77
-0
lines changed

2 files changed

+77
-0
lines changed

drgn_tools/crs_eviction.py

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
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+
8+
from drgn import ObjectAbsentError
9+
from drgn import Program
10+
11+
from drgn_tools.corelens import CorelensModule
12+
from drgn_tools.dentry import dentry_for_each_child
13+
from drgn_tools.dentry import dentry_is_negative
14+
from drgn_tools.file import __path_by_inode
15+
from drgn_tools.lockup import tasks_waiting_fsnotify
16+
from drgn_tools.lockup import tasks_waiting_rcu_gp
17+
from drgn_tools.lockup import tasks_waiting_spinlock
18+
from drgn_tools.task import get_pid
19+
20+
21+
def crs_eviction_waiting_for_rcu(prog: Program) -> None:
22+
"""Different types of issues related to rcu"""
23+
if not tasks_waiting_rcu_gp(prog):
24+
return
25+
26+
# spinlock contention issue
27+
if tasks_waiting_spinlock(prog):
28+
# due to fsnotify
29+
frame_list = tasks_waiting_fsnotify(prog)
30+
if frame_list:
31+
for task, frame in frame_list:
32+
if frame.name == "__fsnotify_update_child_dentry_flags":
33+
if "alias" in frame.locals():
34+
dentry = frame["alias"]
35+
try:
36+
path_name = __path_by_inode(dentry.d_inode)
37+
total_count = 0
38+
negative_count = 0
39+
for child in dentry_for_each_child(dentry):
40+
total_count += 1
41+
if dentry_is_negative(child):
42+
negative_count += 1
43+
except ObjectAbsentError:
44+
continue
45+
46+
print(
47+
"CRS eviction caused by spinlock contention due to fsnotify detected."
48+
)
49+
print(f"PID: {get_pid(task)}")
50+
print(f"Directory being iterated: {path_name}")
51+
print(f"Total dentries: {total_count}")
52+
print(f"Negative dentries: {negative_count}")
53+
if total_count:
54+
print(
55+
f"% Negative dentries: {negative_count / total_count:.2%}"
56+
)
57+
58+
59+
def scan_crs_eviction(prog: Program) -> None:
60+
# run a list of detectors
61+
crs_eviction_waiting_for_rcu(prog)
62+
63+
64+
class CrsEviction(CorelensModule):
65+
"""Detectors for crs eviction related issues"""
66+
67+
name = "crs_eviction"
68+
69+
def run(self, prog: Program, args: argparse.Namespace) -> None:
70+
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)