Whamcloud - gitweb
LU-12461 contrib: Add epython scripts for crash dump analysis
[fs/lustre-release.git] / contrib / debug_tools / epython_scripts / lustrelib.py
1 #!/usr/bin/env python
2 from pykdump.API import *
3
4 """
5 Copyright (c) 2015-2019 Cray Inc. All Rights Reserved.
6 Library of helper functions for Lustre scripts
7 """
8 # hide this file from the output of 'epython scripts'.
9 interactive = False
10
11 """Lustre Hash Table Utilities"""
12
13 CFS_HASH_ADD_TAIL = 1 << 4
14 CFS_HASH_DEPTH = 1 << 12
15 CFS_HASH_TYPE_MASK = CFS_HASH_ADD_TAIL | CFS_HASH_DEPTH
16
17 HH = 0
18 HD = CFS_HASH_DEPTH
19 DH = CFS_HASH_ADD_TAIL
20 DD = CFS_HASH_DEPTH | CFS_HASH_ADD_TAIL
21
22 def hs_get_type(hsh):
23     return hsh.hs_flags & CFS_HASH_TYPE_MASK
24
25 def enum(**enums):
26     return type('Enum', (), enums)
27
28 HS_INFO_FLDS = enum(dtfld=0, hdfld=1,)
29
30 # The type to struct changes and jobid_hash addition were released
31 # in the same version, so use existence of jobid_hash as a substitute
32 # for cfs_hash type changes.
33 if symbol_exists('jobid_hash'):    # 2.11 and later
34     HS_INFO = {
35         HH: ['struct cfs_hash_head', 'hh_head'],
36         HD: ['struct cfs_hash_head_dep', 'hd_head'],
37         DH: ['struct cfs_hash_dhead', 'dh_head'],
38         DD: ['struct cfs_hash_dhead_dep', 'dd_head'],
39     }
40 else:
41     HS_INFO = {
42         HH: ['cfs_hash_head_t', 'hh_head'],
43         HD: ['cfs_hash_head_dep_t', 'hd_head'],
44         DH: ['cfs_hash_dhead_t', 'dh_head'],
45         DD: ['cfs_hash_dhead_dep_t', 'dd_head'],
46     }
47
48 def CFS_HASH_NBKT(hsh):
49     return (1 << (hsh.hs_cur_bits - hsh.hs_bkt_bits))
50
51 def CFS_HASH_BKT_NHLIST(hsh):
52     return (1 << (hsh.hs_bkt_bits))
53
54 def cfs_hash_head_size(hsh):
55     size = getSizeOf(HS_INFO[hs_get_type(hsh)][HS_INFO_FLDS.dtfld])
56     return size
57
58 def cfs_hash_bucket_size(hsh):
59     size = member_offset('struct cfs_hash_bucket', 'hsb_head')
60     size += cfs_hash_head_size(hsh) * CFS_HASH_BKT_NHLIST(hsh) + \
61             hsh.hs_extra_bytes
62     return size
63
64 def cfs_hash_hhead(hsh, bd_bkt, bd_offset):
65     info = HS_INFO[hs_get_type(hsh)]
66     bkt = Addr(bd_bkt) + member_offset('struct cfs_hash_bucket', 'hsb_head')
67     head = readSU(info[HS_INFO_FLDS.dtfld], bkt)
68     offset = member_offset(info[HS_INFO_FLDS.dtfld], info[HS_INFO_FLDS.hdfld])
69     return readSU('struct hlist_head', (Addr(head[bd_offset]) + offset))
70
71 def cfs_hash_get_buckets(hsh):
72     hbuckets = []
73     for idx in range(CFS_HASH_NBKT(hsh)):
74         if hsh.hs_buckets[idx]:
75             hbuckets.append(hsh.hs_buckets[idx])
76     return hbuckets
77
78 def cfs_hash_get_hlist_nodes(hsh, bd_bkt, bd_offset):
79     hlist = readSU('struct hlist_head', cfs_hash_hhead(hsh, bd_bkt, bd_offset))
80     hnodes = []
81     hnode = hlist.first
82     while (hnode and hnode != hlist):
83         hnodes.append(hnode)
84         hnode = hnode.next
85     return hnodes
86
87 def cfs_hash_get_nodes(hsh):
88     hs_nodes = []
89     for bd_bkt in cfs_hash_get_buckets(hsh):
90         for bd_offset in range(CFS_HASH_BKT_NHLIST(hsh)):
91             for hnode in cfs_hash_get_hlist_nodes(hsh, bd_bkt, bd_offset):
92                 hs_nodes.append(hnode)
93     return hs_nodes
94
95 """nid"""
96
97 def LNET_NIDADDR(nid):
98     return (nid & 0xffffffff)
99
100 def LNET_NIDNET(nid):
101     return ((nid >> 32) & 0xffffffff)
102
103 def LNET_NETTYP(net):
104     return ((net >> 16) & 0xffff)
105
106 def LNET_NETNUM(net):
107     return ((net) & 0xffff)
108
109 LNET_NID_ANY = 0xffffffffffffffff
110 LNET_NIDSTR_SIZE = 32
111
112 O2IBLND = 5
113 PTLLND = 4
114 GNILND = 13
115
116 LP_POISON = 0x5a5a5a5a5a5a5a5a
117
118 def nid2str(nid):
119     if nid == LNET_NID_ANY:
120         return 'LNET_NID_ANY'
121     addr = LNET_NIDADDR(nid)
122     net = LNET_NIDNET(nid)
123     lnd = LNET_NETTYP(net)
124     nnum = LNET_NETNUM(net)
125     s = ""
126     if lnd == O2IBLND:
127         s = "%d.%d.%d.%d@o2ib" % \
128             ((addr >> 24) & 0xff, (addr >> 16) & 0xff,
129             (addr >> 8) & 0xff, addr & 0xff)
130     elif lnd == PTLLND:
131         s = "%d@ptl" % addr
132     elif lnd == GNILND:
133         s = "%d@gni" % addr
134     else:
135         nnum = 0
136     if nnum != 0:
137         s = "%s%d" % (s, nnum)
138     return s
139
140 def obd2nidstr(obd):
141     obd_import = readSU('struct obd_import', obd.u.cli.cl_import)
142     nid = LNET_NID_ANY
143     imp_invalid = 1
144     if obd_import and obd_import != 0xffffffffffffffff and \
145        obd_import != LP_POISON:
146         imp_invalid = obd_import.imp_invalid
147
148     if not imp_invalid and obd_import.imp_connection:
149         if Addr(obd_import.imp_obd) == Addr(obd):
150             nid = obd_import.imp_connection.c_peer.nid
151     return nid2str(nid)
152
153 """Miscellaneous"""
154
155 def obd2str(obd, partitions=2):
156     name = obd.obd_name.split('-', partitions)[:partitions]
157     return '-'.join(name)
158
159 def list_empty(head):
160     return head.next == head
161
162 """Red-Black"""
163
164 def rb_first(root):
165     n = root.rb_node
166     if not n:
167         return None
168     while(n.rb_left):
169         n = n.rb_left
170     return n
171
172 def rb_last(root):
173     n = root.rb_node
174     if not n:
175         return None
176     while(n.rb_right):
177         n = n.rb_right
178     return n
179
180 def rb_parent_color(node):
181     return readU64(Addr(node))
182
183 def rb_parent(node):
184     addr = rb_parent_color(node) & ~3
185     return readSU('struct rb_node', addr)
186
187 #The color of the rb_node; 0 denotes red, 1 denotes black
188 def rb_color(node):
189     return rb_parent_color(node) & 1
190
191 def rb_next(node):
192     if rb_parent(node) == node:
193         return None
194     #right child exists
195     if node.rb_right:
196         node = node.rb_right
197         while(node.rb_left):
198             node = node.rb_left
199         return node
200     #no right child
201     parent = rb_parent(node)
202     while(parent and node == parent.rb_right):
203         node = parent
204         parent = rb_parent(node)
205     return parent
206
207 def rb_prev(node):
208     if rb_parent(node) == node:
209         return None
210     #left child exists
211     if node.rb_left:
212         node = node.rb_left
213         while(node.rb_right):
214             node = node.rb_right
215         return node
216     #no left child
217     parent = rb_parent(node)
218     while(parent.rb_left and node == parent.rb_left):
219         node = parent
220         parent = rb_parent(node)
221     return parent
222
223 """LNET Globals"""
224 the_lnet = readSymbol('the_lnet')
225
226 tmpsiz = 256
227
228 LNET_CPT_BITS = the_lnet.ln_cpt_bits
229 LNET_PROC_CPT_BITS = LNET_CPT_BITS + 1
230 LNET_LOFFT_BITS = getSizeOf('loff_t') * 8
231 LNET_PROC_VER_BITS = max((min(LNET_LOFFT_BITS, 64) / 4), 8)
232 LNET_PROC_HASH_BITS = 9
233 LNET_PROC_HOFF_BITS = LNET_LOFFT_BITS - LNET_PROC_CPT_BITS - LNET_PROC_VER_BITS - LNET_PROC_HASH_BITS -1
234 LNET_PROC_HPOS_BITS = LNET_PROC_HASH_BITS + LNET_PROC_HOFF_BITS
235 LNET_PROC_VPOS_BITS = LNET_PROC_HPOS_BITS + LNET_PROC_VER_BITS
236
237 LNET_PROC_CPT_MASK = (1 << LNET_PROC_CPT_BITS) - 1
238 LNET_PROC_VER_MASK = (1 << LNET_PROC_VER_BITS) - 1
239 LNET_PROC_HASH_MASK = (1 << LNET_PROC_HASH_BITS) - 1
240 LNET_PROC_HOFF_MASK = (1 << LNET_PROC_HASH_BITS) - 1
241
242 LNET_PING_FEAT_NI_STATUS = 1 << 1
243
244 HZ = sys_info.HZ