Bug 204773

Summary: Dev mode timelines are missing some kprobes in 5.5
Product: Tools Reporter: Todd Brandt (todd.e.brandt)
Component: pm-graphAssignee: Virtual Assignee for pm-graph (tools_pm_graph)
Status: RESOLVED CODE_FIX    
Severity: normal    
Priority: P1    
Hardware: All   
OS: Linux   
Kernel Version: 5.3.0-rc7 Subsystem:
Regression: No Bisected commit-id:

Description Todd Brandt 2019-09-04 20:42:07 UTC
When running a dev mode timeline with python2, the last few dev mode kprobes are not set properly and thus there is data missing from the timeline.

sudo python2 ./sleepgraph.py -m mem -rtcwake 10 -dev

This doesn't appear to happen in python3

CAUSE:

The problem is with the setVal function in the SystemValues class. It used to disable buffering when writing sysfs values like this:

fp = open(file, mode, 0)

However, in the python3 conversion, this line was changed to remove buffering by removing the 0. Thus when sysfs values are written they are now buffered again.

The dev mode kprobe list is well over 4K, so when it's written to /sys/kernel/debug/tracing/kprobe_events it ends up happening in more than one write. The trace subsystem basically ignores all but the first write and a big section of kprobe data is left out.

SOLUTION:

make the setVal function unbuffered again for both python2 and python3
Comment 1 Todd Brandt 2019-09-04 21:12:19 UTC
Fix has been created and submitted upstream:

https://marc.info/?l=linux-pm&m=156763119501263&w=2

diff --git a/tools/power/pm-graph/sleepgraph.py b/tools/power/pm-graph/sleepgraph.py
index 1794c79a7d1b..f7d1c1f62f86 100755
--- a/tools/power/pm-graph/sleepgraph.py
+++ b/tools/power/pm-graph/sleepgraph.py
@@ -667,19 +667,19 @@ class SystemValues:
 		if linesack < linesout:
 			return False
 		return True
-	def setVal(self, val, file, mode='w'):
+	def setVal(self, val, file):
 		if not os.path.exists(file):
 			return False
 		try:
-			fp = open(file, mode)
-			fp.write(val)
+			fp = open(file, 'wb', 0)
+			fp.write(val.encode())
 			fp.flush()
 			fp.close()
 		except:
 			return False
 		return True
-	def fsetVal(self, val, path, mode='w'):
-		return self.setVal(val, self.tpath+path, mode)
+	def fsetVal(self, val, path):
+		return self.setVal(val, self.tpath+path)
 	def getVal(self, file):
 		res = ''
 		if not os.path.exists(file):