Whamcloud - gitweb
LU-17744 ldiskfs: mballoc stats fixes
[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         try:
85             hnode = hnode.next
86         except (crash.error, IndexError):
87             break
88     return hnodes
89
90 def cfs_hash_get_nodes(hsh):
91     hs_nodes = []
92     for bd_bkt in cfs_hash_get_buckets(hsh):
93         for bd_offset in range(CFS_HASH_BKT_NHLIST(hsh)):
94             for hnode in cfs_hash_get_hlist_nodes(hsh, bd_bkt, bd_offset):
95                 hs_nodes.append(hnode)
96     return hs_nodes
97
98 """nid"""
99
100 def LNET_NIDADDR(nid):
101     return (nid & 0xffffffff)
102
103 def LNET_NIDNET(nid):
104     return ((nid >> 32) & 0xffffffff)
105
106 def LNET_NETTYP(net):
107     return ((net >> 16) & 0xffff)
108
109 def LNET_NETNUM(net):
110     return ((net) & 0xffff)
111
112 LNET_NID_ANY = 0xffffffffffffffff
113 LNET_NIDSTR_SIZE = 32
114
115 SOCKLND = 2
116 O2IBLND = 5
117 PTLLND = 4
118 GNILND = 13
119
120 LP_POISON = 0x5a5a5a5a5a5a5a5a
121
122 def nid2str(nid):
123     if nid == LNET_NID_ANY:
124         return 'LNET_NID_ANY'
125     addr = LNET_NIDADDR(nid)
126     net = LNET_NIDNET(nid)
127     lnd = LNET_NETTYP(net)
128     nnum = LNET_NETNUM(net)
129     s = ""
130     if lnd == O2IBLND:
131         s = "%d.%d.%d.%d@o2ib" % \
132             ((addr >> 24) & 0xff, (addr >> 16) & 0xff,
133             (addr >> 8) & 0xff, addr & 0xff)
134     elif lnd == PTLLND:
135         s = "%d@ptl" % addr
136     elif lnd == GNILND:
137         s = "%d@gni" % addr
138     elif lnd == SOCKLND:
139         s = "%d.%d.%d.%d@tcp" % ((addr >> 24) & 0xff, (addr >> 16) & 0xff,
140                                  (addr >> 8) & 0xff, addr & 0xff)
141     else:
142         nnum = 0
143     if nnum != 0:
144         s = "%s%d" % (s, nnum)
145     return s
146
147 def obd2nidstr(obd):
148     obd_import = readSU('struct obd_import', obd.u.cli.cl_import)
149     nid = LNET_NID_ANY
150     imp_invalid = 1
151     if obd_import and obd_import != 0xffffffffffffffff and \
152        obd_import != LP_POISON:
153         imp_invalid = obd_import.imp_invalid
154
155     if not imp_invalid and obd_import.imp_connection:
156         if Addr(obd_import.imp_obd) == Addr(obd):
157             nid = obd_import.imp_connection.c_peer.nid
158     return nid2str(nid)
159
160 """Miscellaneous"""
161
162 def obd2str(obd, partitions=2):
163     name = obd.obd_name.split('-', partitions)[:partitions]
164     return '-'.join(name)
165
166 def list_empty(head):
167     return head.next == head
168
169 """Red-Black"""
170
171 def rb_first(root):
172     n = root.rb_node
173     if not n:
174         return None
175     while(n.rb_left):
176         n = n.rb_left
177     return n
178
179 def rb_last(root):
180     n = root.rb_node
181     if not n:
182         return None
183     while(n.rb_right):
184         n = n.rb_right
185     return n
186
187 def rb_parent_color(node):
188     return readU64(Addr(node))
189
190 def rb_parent(node):
191     addr = rb_parent_color(node) & ~3
192     return readSU('struct rb_node', addr)
193
194 #The color of the rb_node; 0 denotes red, 1 denotes black
195 def rb_color(node):
196     return rb_parent_color(node) & 1
197
198 def rb_next(node):
199     if rb_parent(node) == node:
200         return None
201     #right child exists
202     if node.rb_right:
203         node = node.rb_right
204         while(node.rb_left):
205             node = node.rb_left
206         return node
207     #no right child
208     parent = rb_parent(node)
209     while(parent and node == parent.rb_right):
210         node = parent
211         parent = rb_parent(node)
212     return parent
213
214 def rb_prev(node):
215     if rb_parent(node) == node:
216         return None
217     #left child exists
218     if node.rb_left:
219         node = node.rb_left
220         while(node.rb_right):
221             node = node.rb_right
222         return node
223     #no left child
224     parent = rb_parent(node)
225     while(parent.rb_left and node == parent.rb_left):
226         node = parent
227         parent = rb_parent(node)
228     return parent
229
230 """LNET Globals"""
231 the_lnet = readSymbol('the_lnet')
232
233 tmpsiz = 256
234
235 LNET_CPT_BITS = the_lnet.ln_cpt_bits
236 LNET_PROC_CPT_BITS = LNET_CPT_BITS + 1
237 LNET_LOFFT_BITS = getSizeOf('loff_t') * 8
238 LNET_PROC_VER_BITS = int(max((min(LNET_LOFFT_BITS, 64) / 4), 8))
239 LNET_PROC_HASH_BITS = 9
240 LNET_PROC_HOFF_BITS = LNET_LOFFT_BITS - LNET_PROC_CPT_BITS - LNET_PROC_VER_BITS - LNET_PROC_HASH_BITS -1
241 LNET_PROC_HPOS_BITS = LNET_PROC_HASH_BITS + LNET_PROC_HOFF_BITS
242 LNET_PROC_VPOS_BITS = LNET_PROC_HPOS_BITS + LNET_PROC_VER_BITS
243
244 LNET_PROC_CPT_MASK = (1 << LNET_PROC_CPT_BITS) - 1
245 LNET_PROC_VER_MASK = (1 << LNET_PROC_VER_BITS) - 1
246 LNET_PROC_HASH_MASK = (1 << LNET_PROC_HASH_BITS) - 1
247 LNET_PROC_HOFF_MASK = (1 << LNET_PROC_HASH_BITS) - 1
248
249 LNET_PING_FEAT_NI_STATUS = 1 << 1
250
251 HZ = sys_info.HZ