From 423d70cebe26a86240448257d798a9cb0de3b6ce Mon Sep 17 00:00:00 2001 From: Shaun Tancheff Date: Wed, 10 Aug 2022 19:33:53 +0700 Subject: [PATCH] Updates for newer kernels While testing with 5.16 there are some changed struct members that need updates. Most notably the change to task_struct.__state breaks in a few places Signed-off-by: Shaun Tancheff --- LinuxDump/Analysis.py | 11 ++++---- LinuxDump/Tasks.py | 66 +++++++++++++++++++++++++++++++++++++++++-- progs/crashinfo.py | 4 +-- progs/hanginfo.py | 9 +++--- progs/pstree.py | 62 ++++------------------------------------ progs/taskinfo.py | 20 +++++++------ 6 files changed, 94 insertions(+), 78 deletions(-) diff --git a/LinuxDump/Analysis.py b/LinuxDump/Analysis.py index 64fdb24..ed9da81 100644 --- a/LinuxDump/Analysis.py +++ b/LinuxDump/Analysis.py @@ -1,6 +1,7 @@ # !/usr/bin/env python # -*- coding: utf-8 -*- # module LinuxDump.Analysis +# vim: tabstop=4 shiftwidth=4 softtabstop=4 noexpandtab: # # -------------------------------------------------------------------- # (C) Copyright 2006-2019 Hewlett Packard Enterprise Development LP @@ -29,8 +30,8 @@ from LinuxDump.inet import proto from LinuxDump.Tasks import (TaskTable, Task, tasksSummary, ms2uptime, - decode_tflags, decode_waitq, TASK_STATE) - + decode_tflags, decode_waitq, TASK_STATE, + getTaskState) from LinuxDump.fregsapi import (search_for_registers, DisasmFlavor) from LinuxDump.BTstack import (exec_bt, verifyFastSet) @@ -244,7 +245,7 @@ def print_pidlist(pids, title = '', verbose = False, maxpids = 10, def check_possible_hang(): T_table = TaskTable() pids_UN = {t.pid for t in T_table.allThreads() \ - if t.ts.state & TASK_STATE.TASK_UNINTERRUPTIBLE} + if getTaskState(t.ts) & TASK_STATE.TASK_UNINTERRUPTIBLE} tot_UN = len(pids_UN) # Now check how many pids are older than 120s mlist = [] @@ -278,7 +279,7 @@ def check_memory_pressure(_funcpids): T_table = TaskTable() for pid in subpids: t = T_table.getByTid(pid) - d[t.state] += 1 + d[getTaskState(t)] += 1 total += 1 if ("TASK_UNINTERRUPTIBLE" in d or total > 20): pylog.warning("Memory pressure detected") @@ -295,7 +296,7 @@ def check_hanging_nfsd(_funcpids): T_table = TaskTable() for pid in subpids: t = T_table.getByTid(pid) - d[t.state] += 1 + d[getTaskState(t)] += 1 total += 1 if ("TASK_UNINTERRUPTIBLE" in d): pylog.warning("Hanging nfsd threads") diff --git a/LinuxDump/Tasks.py b/LinuxDump/Tasks.py index 186eb6d..49ab38d 100755 --- a/LinuxDump/Tasks.py +++ b/LinuxDump/Tasks.py @@ -1,6 +1,7 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- # module LinuxDump.Tasks +# vim: tabstop=4 shiftwidth=4 softtabstop=4 noexpandtab: # # -------------------------------------------------------------------- # (C) Copyright 2006-2020 Hewlett Packard Enterprise Development LP @@ -28,7 +29,7 @@ from pykdump.API import * from pykdump.ASCII_Art import EmbeddedFrames -from LinuxDump import percpu +from LinuxDump import percpu, crashcolor from .inet import proto from .BTstack import exec_bt @@ -127,6 +128,67 @@ else: TASK_STATE = TASK_STATE_26 +# task_struct.__state was task_struct.state +# try the new name and fallback to the old. +def getTaskState(task): + state = None + try: + state = task.__state + except KeyError as kerr: # older kernel, pre 5.14? + state = task.state + return state + +## From pstree.py, shared with taskinfo.py +TASK_RUNNING = 0 +TASK_INTERRUPTIBLE = 1 +TASK_UNINTERRUPTIBLE = 2 +__TASK_STOPPED = 4 +__TASK_TRACED = 8 +EXIT_ZOMBIE = 16 +EXIT_DEAD = 32 +TASK_DEAD = 64 + +def task_state_color(state): + if isinstance(state, int): + state = state & 0x7f + return { + TASK_RUNNING : crashcolor.BLUE, + TASK_INTERRUPTIBLE : crashcolor.RESET, + TASK_UNINTERRUPTIBLE : crashcolor.RED, + __TASK_STOPPED : crashcolor.CYAN, + __TASK_TRACED : crashcolor.MAGENTA, + EXIT_ZOMBIE : crashcolor.YELLOW, + EXIT_DEAD : crashcolor.LIGHTRED, + TASK_DEAD : crashcolor.LIGHTRED, + "TASK_RUNNING" : crashcolor.BLUE, + "TASK_INTERRUPTIBLE" : crashcolor.RESET, + "TASK_UNINTERRUPTIBLE" : crashcolor.RED, + "TASK_STOPPED" : crashcolor.CYAN, + "TASK_ZOMBIE" : crashcolor.YELLOW, + "TASK_DEAD" : crashcolor.LIGHTRED, + }[state] + + +def task_state_str(state): + if isinstance(state, int): + state = state & 0x7f + return { + TASK_RUNNING: "RU", + TASK_INTERRUPTIBLE: "IN", + TASK_UNINTERRUPTIBLE: "UN", + __TASK_STOPPED: "ST", + __TASK_TRACED: "TR", + EXIT_ZOMBIE: "ZO", + EXIT_DEAD: "DE", + TASK_DEAD: "DE", + "TASK_RUNNING" : "RU", + "TASK_INTERRUPTIBLE" : "IN", + "TASK_UNINTERRUPTIBLE" : "UN", + "TASK_STOPPED" : "ST", + "TASK_ZOMBIE" : "ZO", + "TASK_DEAD" : "DE", + }[state] + # ------------------------------------------------------------------- # We have a global variable 'struct task_struct init_task;', @@ -185,7 +247,7 @@ def __get_rq(self): # -- Get Task State in a symbolic format -- def __get_state(self): try: - st = task_state2str(self.ts.state) + st = getTaskState(self.ts) except: st = '??' pylog.error('corrupted task ', self.ts) diff --git a/progs/crashinfo.py b/progs/crashinfo.py index 102eff8..207bbcf 100755 --- a/progs/crashinfo.py +++ b/progs/crashinfo.py @@ -22,7 +22,7 @@ fastSubroutineStacks, verifyFastSet) from LinuxDump.kmem import parse_kmemf, print_Zone from LinuxDump.Tasks import (TaskTable, Task, tasksSummary, getRunQueues, - TASK_STATE, sched_clock2ms, decode_waitq) + TASK_STATE, sched_clock2ms, decode_waitq, getTaskState) from LinuxDump.Analysis import (check_possible_hang, check_saphana, check_memory_pressure, check_hanging_nfsd, print_wait_for_AF_UNIX) @@ -992,7 +992,7 @@ def check_UNINTERRUPTIBLE(): bts = [] count = 0 for t in tt.allThreads(): - if (t.ts.state & TASK_STATE.TASK_UNINTERRUPTIBLE): + if (getTaskState(t.ts) & TASK_STATE.TASK_UNINTERRUPTIBLE): pid = t.pid count += 1 # crash can miss some threads when there are pages missing diff --git a/progs/hanginfo.py b/progs/hanginfo.py index 9c3e7cf..0b69928 100755 --- a/progs/hanginfo.py +++ b/progs/hanginfo.py @@ -18,7 +18,8 @@ from pykdump.API import * from LinuxDump.fs import * from LinuxDump.Tasks import (TaskTable, Task, tasksSummary, ms2uptime, - decode_tflags, decode_waitq, TASK_STATE) + decode_tflags, decode_waitq, TASK_STATE, + getTaskState) from LinuxDump.BTstack import (exec_bt, bt_mergestacks, fastSubroutineStacks, verifyFastSet) @@ -99,7 +100,7 @@ def print_header(msg, n = None): #@memoize_cond(CU_LIVE) def getUNTasks(): return {t.pid for t in T_table.allThreads() \ - if t.ts.state & TASK_STATE.TASK_UNINTERRUPTIBLE} + if getTaskState(t.ts) & TASK_STATE.TASK_UNINTERRUPTIBLE} # Remove a list of pids from the provided dictionary def remove_pidlist(pset, pids): @@ -226,7 +227,7 @@ def get_sema_owners(): for t in tt.allThreads(): if (not t.pid in goodpids): continue - if (t.ts.state in (TASK_STATE.TASK_RUNNING, TASK_STATE.TASK_UNINTERRUPTIBLE)): + if (getTaskState(t.ts) in (TASK_STATE.TASK_RUNNING, TASK_STATE.TASK_UNINTERRUPTIBLE)): if (member_size("struct mm_struct", "mmap_sem") != -1): out[t.mm.mmap_sem].append(t.pid) else: @@ -247,7 +248,7 @@ def summarize_subroutines(funcnames, title = None): total = 0 for pid in subpids: t = T_table.getByTid(pid) - d[t.state] += 1 + d[getTaskState(t)] += 1 total += 1 # Print if (title): diff --git a/progs/pstree.py b/progs/pstree.py index 9101942..e1f463a 100644 --- a/progs/pstree.py +++ b/progs/pstree.py @@ -1,4 +1,5 @@ #!/usr/bin/env/python +# vim: tabstop=4 shiftwidth=4 softtabstop=4 noexpandtab: # -------------------------------------------------------------------- # (C) Copyright 2018-2019 Red Hat, Inc. # @@ -21,7 +22,8 @@ # GNU General Public License for more details. from pykdump.API import * -from LinuxDump.Tasks import Task, TaskTable +from LinuxDump.Tasks import (Task, TaskTable, getTaskState, + task_state_color, task_state_str) from LinuxDump import crashcolor import sys @@ -66,59 +68,6 @@ def print_pstree(options): print ("\n\nTotal %s tasks printed" % (pid_cnt)) -TASK_RUNNING = 0 -TASK_INTERRUPTIBLE = 1 -TASK_UNINTERRUPTIBLE = 2 -__TASK_STOPPED = 4 -__TASK_TRACED = 8 -EXIT_ZOMBIE = 16 -EXIT_DEAD = 32 -TASK_DEAD = 64 - -def task_state_color(state): - if isinstance(state, int): - state = state & 0x7f - - return { - TASK_RUNNING : crashcolor.BLUE, - TASK_INTERRUPTIBLE : crashcolor.RESET, - TASK_UNINTERRUPTIBLE : crashcolor.RED, - __TASK_STOPPED : crashcolor.CYAN, - __TASK_TRACED : crashcolor.MAGENTA, - EXIT_ZOMBIE : crashcolor.YELLOW, - EXIT_DEAD : crashcolor.LIGHTRED, - TASK_DEAD : crashcolor.LIGHTRED, - "TASK_RUNNING" : crashcolor.BLUE, - "TASK_INTERRUPTIBLE" : crashcolor.RESET, - "TASK_UNINTERRUPTIBLE" : crashcolor.RED, - "TASK_STOPPED" : crashcolor.CYAN, - "TASK_ZOMBIE" : crashcolor.YELLOW, - "TASK_DEAD" : crashcolor.LIGHTRED, - }[state] - - -def task_state_str(state): - if isinstance(state, int): - state = state & 0x7f - - return { - TASK_RUNNING: "RU", - TASK_INTERRUPTIBLE: "IN", - TASK_UNINTERRUPTIBLE: "UN", - __TASK_STOPPED: "ST", - __TASK_TRACED: "TR", - EXIT_ZOMBIE: "ZO", - EXIT_DEAD: "DE", - TASK_DEAD: "DE", - "TASK_RUNNING" : "RU", - "TASK_INTERRUPTIBLE" : "IN", - "TASK_UNINTERRUPTIBLE" : "UN", - "TASK_STOPPED" : "ST", - "TASK_ZOMBIE" : "ZO", - "TASK_DEAD" : "DE", - }[state] - - def print_branch(depth, first): global branch_locations global branch_bar @@ -167,7 +116,8 @@ def print_task(task, depth, first, options): if (task.comm != 0): comm_str = task.comm - task_color = task_state_color(task.state) + state = getTaskState(task) + task_color = task_state_color(state) if task_color != crashcolor.RESET: crashcolor.set_color(task_color) @@ -175,7 +125,7 @@ def print_task(task, depth, first, options): (comm_str, "(" + str(task.pid) + ")" if options.print_pid else "", - "[" + task_state_str(task.state) +"]" + "[" + task_state_str(state) +"]" if options.print_state else "", thread_str)) print ("%s" % (print_str), end='') diff --git a/progs/taskinfo.py b/progs/taskinfo.py index 562ccb4..73e379a 100755 --- a/progs/taskinfo.py +++ b/progs/taskinfo.py @@ -1,5 +1,6 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- +# vim: tabstop=4 shiftwidth=4 softtabstop=4 noexpandtab: # -------------------------------------------------------------------- @@ -17,12 +18,12 @@ from LinuxDump import percpu from LinuxDump.Tasks import (TaskTable, Task, tasksSummary, ms2uptime, - decode_tflags, print_namespaces_info, print_memory_stats) + decode_tflags, print_namespaces_info, print_memory_stats, getTaskState, + task_state_str) from LinuxDump.BTstack import exec_bt, bt_summarize from LinuxDump.fs import get_dentry_name - debug = API_options.debug # The following is for x86/x86_64 @@ -72,7 +73,7 @@ def gid_t(v): def printTaskDetails(t): - sstate = t.state[5:7] + sstate = task_state_str(getTaskState(t)) print ("---- %6d(%s) %s %s" % (t.pid, sstate, str(t.ts), t.comm)) print(" cpu", t.cpu) parent = t.parent @@ -144,13 +145,14 @@ def printTaskDetails(t): if u.hasField("files"): print ("\t processes={} files={}{}".format( atomic_t(u.processes), atomic_t(u.files), extra)) - else: - print ("\t processes={}{}".format( - atomic_t(u.processes), extra)) + elif u.hasField("processes"): + print ("\t processes={}{}".format(atomic_t(u.processes), extra)) if (c.hasField("group_info")): g = c.group_info ngroups = g.ngroups - small_block = g.small_block + small_block = "" + if g.hasField("small_block"): + small_block = g.small_block else: ngroups = t.ngroups small_block = t.groups @@ -243,7 +245,7 @@ def printTasks(reverse = False, maxtoprint = -1): if (taskstates_filter): out1 = [] for *group, t in out: - sstate = t.state[5:7] + sstate = task_state_str(getTaskState(t)) if (sstate in taskstates_filter): out1.append((*group, t)) out = out1 @@ -270,7 +272,7 @@ def printTasks(reverse = False, maxtoprint = -1): if (pid is None): print(" ") continue - sstate = t.state[5:7] + sstate = task_state_str(getTaskState(t)) tgid = t.tgid pid_template = " {:6d}" if (pid != tgid):