def check_mmap_sem(tasksrem): waiters = {} for addr in stacks_helper.alltaskaddrs: task = readSU("struct task_struct", addr) if (not task.mm or not task.mm.mmap_sem): continue s = task.mm.mmap_sem cmsg = "task={} mmap_sem={}".format(task, s) with MsgExtra(cmsg): wtasks = get_rwsemaphore_tasks(s) pids = [t.pid for t in wtasks] if (pids): waiters[s] = pids mmapsem_waiters = waiters possible_owners = get_sema_owners() if (mmapsem_waiters): print_header("Waiting on mmap semaphores") for sema, pids in mmapsem_waiters.items(): print(" --", sema) print_pidlist(pids, maxpids=_MAXPIDS, verbose=_VERBOSE, sortbytime=_SORTBYTIME) powners = possible_owners.get(sema, None) if (powners): pid_set = set(pids) powners = set(powners) # Leave only those powners that are not in pids rem = powners - pid_set print(" Possible owners:", list(rem)) for o in rem: add_resource_pid(o) remove_pidlist(tasksrem, pids)
def check_kthread_create_list(tasksrem): try: head = ListHead(readSymbol("kthread_create_list"), "struct kthread_create_info") except TypeError: return tasks = [] for create in head.list: tasks += decode_waitq(create.done.wait) pids_on_the_queue = [t.pid for t in tasks] # Check pids of processes having kthread_create_on_node extra = _funcpids("kthread_create_on_node") extra = list(extra - set(pids_on_the_queue)) if (tasks): print_header("Waiting for kthreadd") print_pidlist(pids_on_the_queue, title="On the queue: ", maxpids=_MAXPIDS, verbose=_VERBOSE, sortbytime=_SORTBYTIME) if (extra): print(" Dequeued but not processed yet: {}".format(extra)) remove_pidlist(tasksrem, pids_on_the_queue + extra)
def summarize_subroutines(funcnames, title=None): subpids = _funcpids(funcnames) # funcnames are specified using | operator if (not subpids): return if (len(subpids) < 100): verifyFastSet(subpids, funcnames) if (not subpids): return d = defaultdict(int) total = 0 for pid in subpids: t = T_table.getByTid(pid) d[t.state] += 1 total += 1 # Print if (title): header = "There are {} threads {}".format(total, title) else: header = "There are {} threads doing {}".format(total, funcnames) print_header(header) for k, v in d.items(): print(" {:3d} in {}".format(v, k)) print_pidlist(subpids, maxpids=_MAXPIDS, verbose=_VERBOSE, sortbytime=_SORTBYTIME)
def check_throttle_direct_reclaim(tasksrem): pids = _funcpids(__tdr_func) verifyFastSet(pids, __tdr_func) if (pids): print_header("Waiting for kswapd") print_pidlist(pids, maxpids=_MAXPIDS, verbose=_VERBOSE, sortbytime=_SORTBYTIME, statefilter=('UN', )) remove_pidlist(tasksrem, pids)
def check_stack_and_print(funcname, tasksrem, txt=None): pids = _funcpids(funcname) & tasksrem verifyFastSet(pids, funcname) if (not pids): return if (txt is None): txt = funcname print_header("Waiting in {}".format(txt)) print_pidlist(pids, maxpids=_MAXPIDS, verbose=_VERBOSE, sortbytime=_SORTBYTIME) add_resource_pid(txt, set(pids)) remove_pidlist(tasksrem, pids)
def check_inode_mutexes(tasksrem): goodpids = _funcpids(__mutexfunc +\ "| __mutex_lock_killable_slowpath") inode_addrs = {} for pid in goodpids: finfo = pidFiles(pid).files for fd in finfo: fields = finfo[fd] inode_addr = fields[2] ftype = fields[3] path = fields[4] if (ftype not in ('REG', 'DIR', 'PIPE')): continue inode_addrs[inode_addr] = path #print(len(inode_addrs)) waiters = {} for inodeaddr, v in inode_addrs.items(): inode = readSU("struct inode", inodeaddr) #print(hex(inode), v) # 1: unlocked, 0: locked, negative: locked, possible waiters counter = inode.i_mutex.count.counter if (counter >= 0): continue mutex = inode.i_mutex print(mutex) wait_tasks = get_mutex_waiters(mutex) pids = [t.pid for t in wait_tasks] waiters[inode] = (v, pids) mutex_waiters = waiters if (mutex_waiters): print_header("Waiting on inode mutexes") for inode, (fn, pids) in mutex_waiters.items(): print(" --", inode, fn) print_mutex(inode.i_mutex, set(pids)) print_pidlist(pids, maxpids=_MAXPIDS, verbose=_VERBOSE, sortbytime=_SORTBYTIME) remove_pidlist(tasksrem, pids)
def check_other_mutexes(tasksrem): #print(mutexlist) mutexlist = set() goodpids = _funcpids(__mutexfunc) for pid in tasksrem: if (not pid in goodpids): #if (not bt.hasfunc(__mutexfunc)): continue maddr = get_tentative_arg(pid, __mutexfunc, 0) #print("pid={} addr={:#x} OK={}".format(pid, maddr, if_mutexOK(maddr))) if (maddr and if_mutexOK(maddr)): mutex = readSU("struct mutex", maddr) mutexlist.add(mutex) #print("pid={}, mutex={}".format(pid, mutex)) continue if (not mutexlist): return # Now print info about each found mutex once = TrueOnce(1) for mutex in mutexlist: try: owner = mutex.Owner except KeyError: owner = None # Sometimes we cannot get this mutex try: pids = [t.pid for t in get_mutex_waiters(mutex)] except: pylog.warning("Cannot get waiters for mutex {}".format(mutex)) continue if (owner and not pids): continue if (once): print_header("Waiting on mutexes") print_mutex(mutex, set(pids)) print_pidlist(pids, maxpids=_MAXPIDS, verbose=_VERBOSE, sortbytime=_SORTBYTIME) remove_pidlist(tasksrem, pids)
def check_congestion_queues(tasksrem): # Congestion queues for i, wqh in enumerate(readSymbol("congestion_wqh")): pids = [] try: text = exec_crash_command("waitq 0x%x" % long(wqh)).strip() except crash.error: continue if (not re.match(r'^.*is empty$', text)): for l in text.splitlines(): fields = l.split() pids.append(int(fields[1])) if (pids): if (i == 0): print(" ---- waiting on the read congestion queue ---") else: print(" ---- waiting on the write congestion queue ---") print_pidlist(pids, maxpids=_MAXPIDS, verbose=_VERBOSE, sortbytime=_SORTBYTIME) remove_pidlist(tasksrem, pids)