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