xref: /spdk/scripts/gdb_macros.py (revision 784b9d48746955f210926648a0131f84f58de76f)
1#   SPDX-License-Identifier: BSD-3-Clause
2#   Copyright (C) 2019 Intel Corporation.
3#
4
5import gdb
6
7
8class SpdkTailqList(object):
9
10    def __init__(self, list_pointer, list_member, tailq_name_list):
11        self.list_pointer = list_pointer
12        self.tailq_name_list = tailq_name_list
13        self.list_member = list_member
14        self.list = gdb.parse_and_eval(self.list_pointer)
15
16    def __iter__(self):
17        curr = self.list['tqh_first']
18        while curr:
19            yield self.list_member(curr)
20            for tailq_name in self.tailq_name_list:
21                curr = curr[tailq_name]
22            curr = curr['tqe_next']
23
24
25class SpdkNormalTailqList(SpdkTailqList):
26
27    def __init__(self, list_pointer, list_member):
28        super(SpdkNormalTailqList, self).__init__(list_pointer, list_member,
29                                                  ['tailq'])
30
31
32class SpdkRbTree(object):
33
34    def __init__(self, tree_pointer, tree_member, tree_name_list):
35        self.tree_pointer = tree_pointer
36        self.tree_name_list = tree_name_list
37        self.tree_member = tree_member
38        self.tree = gdb.parse_and_eval(self.tree_pointer)
39
40    def get_left_node(self, node):
41        return node['node']['rbe_left']
42
43    def get_right_node(self, node):
44        return node['node']['rbe_right']
45
46    def traverse_rb_tree(self, node):
47        if node:
48            self.rb_list.append(node)
49            self.traverse_rb_tree(self.get_left_node(node))
50            self.traverse_rb_tree(self.get_right_node(node))
51
52    def __iter__(self):
53        self.rb_list = []
54        tree_top = self.tree['rbh_root']
55        if tree_top:
56            self.traverse_rb_tree(tree_top)
57            for rb_node in self.rb_list:
58                yield self.tree_member(rb_node)
59        else:
60            yield
61
62
63class SpdkArr(object):
64
65    def __init__(self, arr_pointer, num_elements, element_type):
66        self.arr_pointer = arr_pointer
67        self.num_elements = num_elements
68        self.element_type = element_type
69
70    def __iter__(self):
71        for i in range(0, self.num_elements):
72            curr = (self.arr_pointer + i).dereference()
73            if (curr == 0x0):
74                continue
75            yield self.element_type(curr)
76
77
78class SpdkPrintCommand(gdb.Command):
79
80    def __init__(self, name, element_list):
81        self.element_list = element_list
82        gdb.Command.__init__(self, name,
83                             gdb.COMMAND_DATA,
84                             gdb.COMPLETE_SYMBOL,
85                             True)
86
87    def print_element_list(self, element_list):
88        first = True
89        for element in element_list:
90            if first:
91                first = False
92            else:
93                print("---------------")
94            print("\n" + str(element) + "\n")
95
96    def invoke(self, arg, from_tty):
97        self.print_element_list(self.element_list)
98
99
100class SpdkObject(object):
101
102    def __init__(self, gdb_obj):
103        self.obj = gdb_obj
104
105    def get_name(self):
106        return self.obj['name']
107
108    def __str__(self):
109        s = "SPDK object of type %s at %s" % (self.type_name, str(self.obj))
110        s += '\n((%s*) %s)' % (self.type_name, str(self.obj))
111        s += '\nname %s' % self.get_name()
112        return s
113
114
115class IoDevice(SpdkObject):
116
117    type_name = 'struct io_device'
118
119
120class IoDevices(SpdkRbTree):
121
122    def __init__(self):
123        super(IoDevices, self).__init__('g_io_devices', IoDevice, ['rbh_root'])
124
125
126class spdk_print_io_devices(SpdkPrintCommand):
127
128    def __init__(self):
129        io_devices = IoDevices()
130        name = 'spdk_print_io_devices'
131        super(spdk_print_io_devices, self).__init__(name, io_devices)
132
133
134class Bdev(SpdkObject):
135
136    type_name = 'struct spdk_bdev'
137
138
139class BdevMgrBdevs(SpdkTailqList):
140
141    def __init__(self):
142        tailq_name_list = ['internal', 'link']
143        super(BdevMgrBdevs, self).__init__('g_bdev_mgr->bdevs', Bdev, tailq_name_list)
144
145
146class spdk_print_bdevs(SpdkPrintCommand):
147    name = 'spdk_print_bdevs'
148
149    def __init__(self):
150        bdevs = BdevMgrBdevs()
151        super(spdk_print_bdevs, self).__init__(self.name, bdevs)
152
153
154class spdk_find_bdev(spdk_print_bdevs):
155
156    name = 'spdk_find_bdev'
157
158    def invoke(self, arg, from_tty):
159        print(arg)
160        bdev_query = [bdev for bdev in self.element_list
161                      if str(bdev.get_name()).find(arg) != -1]
162        if bdev_query == []:
163            print("Cannot find bdev with name %s" % arg)
164            return
165
166        self.print_element_list(bdev_query)
167
168
169class NvmfSubsystem(SpdkObject):
170
171    type_name = 'struct spdk_nvmf_subsystem'
172
173    def __init__(self, ptr):
174        self.ptr = ptr
175        gdb_obj = self.ptr.cast(gdb.lookup_type(self.type_name).pointer())
176        super(NvmfSubsystem, self).__init__(gdb_obj)
177
178    def get_name(self):
179        return self.obj['subnqn']
180
181    def get_id(self):
182        return int(self.obj['id'])
183
184    def get_ns_list(self):
185        max_nsid = int(self.obj['max_nsid'])
186        ns_list = []
187        for i in range(0, max_nsid):
188            nsptr = (self.obj['ns'] + i).dereference()
189            if nsptr == 0x0:
190                continue
191            ns = nsptr.cast(gdb.lookup_type('struct spdk_nvmf_ns').pointer())
192            ns_list.append(ns)
193        return ns_list
194
195    def __str__(self):
196        s = super(NvmfSubsystem, self).__str__()
197        s += '\nnqn %s' % self.get_name()
198        s += '\nID %d' % self.get_id()
199        for ns in self.get_ns_list():
200            s += '\t%s' % str(ns)
201        return s
202
203
204class SpdkNvmfTgtSubsystems(SpdkArr):
205
206    def get_num_subsystems(self):
207        try:  # version >= 18.11
208            return int(self.spdk_nvmf_tgt['max_subsystems'])
209        except RuntimeError:  # version < 18.11
210            return int(self.spdk_nvmf_tgt['opts']['max_subsystems'])
211
212    def __init__(self):
213        self.spdk_nvmf_tgt = gdb.parse_and_eval("g_spdk_nvmf_tgt")
214        subsystems = gdb.parse_and_eval("g_spdk_nvmf_tgt->subsystems")
215        super(SpdkNvmfTgtSubsystems, self).__init__(subsystems,
216                                                    self.get_num_subsystems(),
217                                                    NvmfSubsystem)
218
219
220class spdk_print_nvmf_subsystems(SpdkPrintCommand):
221
222    def __init__(self):
223        name = 'spdk_print_nvmf_subsystems'
224        nvmf_tgt_subsystems = SpdkNvmfTgtSubsystems()
225        super(spdk_print_nvmf_subsystems, self).__init__(name, nvmf_tgt_subsystems)
226
227
228class IoChannel(SpdkObject):
229
230    type_name = 'struct spdk_io_channel'
231
232    def get_ref(self):
233
234        return int(self.obj['ref'])
235
236    def get_device(self):
237        return self.obj['dev']
238
239    def get_device_name(self):
240        return self.obj['dev']['name']
241
242    def get_name(self):
243        return ""
244
245    def __str__(self):
246        s = super(IoChannel, self).__str__() + '\n'
247        s += 'ref %d\n' % self.get_ref()
248        s += 'device %s (%s)\n' % (self.get_device(), self.get_device_name())
249        return s
250
251
252class IoChannels(SpdkRbTree):
253
254    def __init__(self, tree_obj):
255        self.tree_name_list = ['rbh_root']
256        self.tree_member = IoChannel
257        self.tree = tree_obj
258
259
260class SpdkThread(SpdkObject):
261
262    type_name = 'struct spdk_thread'
263
264    def __init__(self, gdb_obj):
265        super(SpdkThread, self).__init__(gdb_obj)
266        self.io_channels = IoChannels(self.obj['io_channels'])
267
268    def __str__(self):
269        s = super(SpdkThread, self).__str__() + '\n'
270        s += "IO Channels:\n"
271        for io_channel in self.get_io_channels():
272            channel_lines = str(io_channel).split('\n')
273            s += '\n'.join('\t%s' % line for line in channel_lines if line is not '')
274            s += '\n'
275            s += '\t---------------\n'
276            s += '\n'
277        return s
278
279    def get_io_channels(self):
280        return self.io_channels
281
282
283class SpdkThreads(SpdkNormalTailqList):
284
285    def __init__(self):
286        super(SpdkThreads, self).__init__('g_threads', SpdkThread)
287
288
289class spdk_print_threads(SpdkPrintCommand):
290
291    def __init__(self):
292        name = "spdk_print_threads"
293        threads = SpdkThreads()
294        super(spdk_print_threads, self).__init__(name, threads)
295
296
297class spdk_load_macros(gdb.Command):
298
299    def __init__(self):
300        gdb.Command.__init__(self, 'spdk_load_macros',
301                             gdb.COMMAND_DATA,
302                             gdb.COMPLETE_SYMBOL,
303                             True)
304        self.loaded = False
305
306    def invoke(self, arg, from_tty):
307        if arg == '--reload':
308            print('Reloading spdk information')
309            reload = True
310        else:
311            reload = False
312
313        if self.loaded and not reload:
314            return
315
316        spdk_print_threads()
317        spdk_print_bdevs()
318        spdk_print_io_devices()
319        spdk_print_nvmf_subsystems()
320        spdk_find_bdev()
321
322
323spdk_load_macros()
324