4 Copyright 2015-2019 Cray Inc. All Rights Reserved
5 Utility to list granted and waiting ldlm locks.
8 from pykdump.API import *
12 import lustrelib as ll
13 from crashlib.input import toint
15 from traceback import print_exc
17 description = "Dumps lists of granted and waiting ldlm locks for each namespace."
36 def lockmode2str(mode):
37 return LOCKMODES.get(mode, "??")
39 def ldlm_dump_lock(lock, pos, lstname):
43 print " NULL LDLM lock"
45 print " -- Lock: (ldlm_lock) %#x/%#x (rc: %d) (pos: %d/%s) (pid: %d)" % \
46 (Addr(lock), lock.l_handle.h_cookie, lock.l_refc.counter,
47 pos, lstname, lock.l_pid)
48 if(lock.l_conn_export):
49 obd = lock.l_conn_export.exp_obd
50 if(lock.l_export and lock.l_export.exp_connection):
51 print " Node: NID %s (remote: %#x) export" % \
52 (ll.nid2str(lock.l_export.exp_connection.c_peer.nid),
53 lock.l_remote_handle.cookie)
57 imp = obd.u.cli.cl_import
58 print " Node: NID %s (remote: %#x) import " % \
59 (ll.nid2str(imp.imp_connection.c_peer.nid),
60 lock.l_remote_handle.cookie)
63 print " Resource: %#x [0x%x:0x%x:0x%x].%x" % \
70 print " Req mode: %s, grant mode: %s, rc: %d, read: %d, \
71 write: %d flags: %#x" % (lockmode2str(lock.l_req_mode),
72 lockmode2str(lock.l_granted_mode),
73 lock.l_refc.counter, lock.l_readers, lock.l_writers,
76 lr_type = lock.l_resource.lr_type
77 if(lr_type == enum_LDLM_EXTENT):
78 print " Extent: %d -> %d (req %d-%d)" % \
79 (lock.l_policy_data.l_extent.start,
80 lock.l_policy_data.l_extent.end,
81 lock.l_req_extent.start, lock.l_req_extent.end)
82 elif(lr_type == enum_LDLM_FLOCK):
83 print " Pid: %d Flock: 0x%x -> 0x%x" % \
84 (lock.l_policy_data.l_flock.pid,
85 lock.l_policy_data.l_flock.start,
86 lock.l_policy_data.l_flock.end)
87 elif(lr_type == enum_LDLM_IBITS):
88 print " Bits: %#x" % \
89 (lock.l_policy_data.l_inodebits.bits)
91 def ldlm_dump_resource(res):
92 res_lr_granted = readSU('struct list_head', Addr(res.lr_granted))
93 res_lr_waiting = readSU('struct list_head', Addr(res.lr_waiting))
94 print "-- Resource: (ldlm_resource) %#x [0x%x:0x%x:0x%x].%x (rc: %d)" % \
95 (Addr(res), res.lr_name.name[0], res.lr_name.name[1],
96 res.lr_name.name[2], res.lr_name.name[3], res.lr_refcount.counter)
97 if not ll.list_empty(res_lr_granted):
99 print " Granted locks: "
100 tmp = res_lr_granted.next
101 while(tmp != res_lr_granted):
103 lock = readSU('struct ldlm_lock',
104 Addr(tmp)-member_offset('struct ldlm_lock', 'l_res_link'))
105 ldlm_dump_lock(lock, pos, "grnt")
107 if not ll.list_empty(res_lr_waiting):
109 print " Waiting locks: "
110 tmp = res_lr_waiting.next
111 while(tmp != res_lr_waiting):
113 lock = readSU('struct ldlm_lock',
114 Addr(tmp)-member_offset('struct ldlm_lock', 'l_res_link'))
115 ldlm_dump_lock(lock, pos, "wait")
118 def print_namespace(ns, client_server):
119 print "Namespace: (ldlm_namespace) %#x, %s\t(rc: %d, side: %s)\tpoolcnt: %d unused: %d" % \
120 (Addr(ns), ll.obd2str(ns.ns_obd), ns.ns_bref.counter,
121 client_server, ns.ns_pool.pl_granted.counter, ns.ns_nr_unused)
123 def ldlm_dump_ns_resources(ns):
126 for hnode in ll.cfs_hash_get_nodes(ns.ns_rs_hash):
127 offset = member_offset('struct ldlm_resource', 'lr_hash')
128 res = readSU('struct ldlm_resource', Addr(hnode) - offset)
129 ldlm_dump_resource(res)
131 def ldlm_dump_all_namespaces(ns_name, client_server):
132 ns_list = readSymbol(ns_name)
133 for ns in readSUListFromHead(ns_list, 'ns_list_chain', 'struct ldlm_namespace'):
134 print_namespace(ns, client_server)
135 ldlm_dump_ns_resources(ns)
137 def ldlm_dumplocks():
139 ns = readSU('struct ldlm_namespace', args.ns_addr)
140 print_namespace(ns, "")
141 ldlm_dump_ns_resources(ns)
143 ldlm_dump_all_namespaces('ldlm_srv_namespace_list', "server")
144 ldlm_dump_all_namespaces('ldlm_cli_active_namespace_list', "client")
145 ldlm_dump_all_namespaces('ldlm_cli_inactive_namespace_list', "inactive")
147 if __name__ == "__main__":
148 description = "Dumps lists of granted and waiting locks for each namespace. " + \
149 "Requires Lustre .ko files to be loaded (see mod command)."
150 parser = argparse.ArgumentParser(description=description)
151 parser.add_argument("-n", dest="nflag", action='store_true',
152 help="Print only namespace information")
153 parser.add_argument("ns_addr", nargs="?", default=[], type=toint,
154 help="Print only locks under namespace at given address")
155 args = parser.parse_args()