numam-spdk/scripts/gdb_macros.py

290 lines
7.7 KiB
Python
Raw Permalink Normal View History

import gdb
class SpdkTailqList(object):
def __init__(self, list_pointer, list_member, tailq_name_list):
self.list_pointer = list_pointer
self.tailq_name_list = tailq_name_list
self.list_member = list_member
self.list = gdb.parse_and_eval(self.list_pointer)
def __iter__(self):
curr = self.list['tqh_first']
while curr:
yield self.list_member(curr)
for tailq_name in self.tailq_name_list:
curr = curr[tailq_name]
curr = curr['tqe_next']
class SpdkNormalTailqList(SpdkTailqList):
def __init__(self, list_pointer, list_member):
super(SpdkNormalTailqList, self).__init__(list_pointer, list_member,
['tailq'])
class SpdkArr(object):
def __init__(self, arr_pointer, num_elements, element_type):
self.arr_pointer = arr_pointer
self.num_elements = num_elements
self.element_type = element_type
def __iter__(self):
for i in range(0, self.num_elements):
curr = (self.arr_pointer + i).dereference()
if (curr == 0x0):
continue
yield self.element_type(curr)
class SpdkPrintCommand(gdb.Command):
def __init__(self, name, element_list):
self.element_list = element_list
gdb.Command.__init__(self, name,
gdb.COMMAND_DATA,
gdb.COMPLETE_SYMBOL,
True)
def print_element_list(self, element_list):
first = True
for element in element_list:
if first:
first = False
else:
print("---------------")
print("\n" + str(element) + "\n")
def invoke(self, arg, from_tty):
self.print_element_list(self.element_list)
class SpdkObject(object):
def __init__(self, gdb_obj):
self.obj = gdb_obj
def get_name(self):
return self.obj['name']
def __str__(self):
s = "SPDK object of type %s at %s" % (self.type_name, str(self.obj))
s += '\n((%s*) %s)' % (self.type_name, str(self.obj))
s += '\nname %s' % self.get_name()
return s
class IoDevice(SpdkObject):
type_name = 'struct io_device'
class IoDevices(SpdkTailqList):
def __init__(self):
super(IoDevices, self).__init__('g_io_devices', IoDevice, ['tailq'])
class spdk_print_io_devices(SpdkPrintCommand):
def __init__(self):
io_devices = IoDevices()
name = 'spdk_print_io_devices'
super(spdk_print_io_devices, self).__init__(name, io_devices)
class Bdev(SpdkObject):
type_name = 'struct spdk_bdev'
class BdevMgrBdevs(SpdkTailqList):
def __init__(self):
tailq_name_list = ['internal', 'link']
super(BdevMgrBdevs, self).__init__('g_bdev_mgr->bdevs', Bdev, tailq_name_list)
class spdk_print_bdevs(SpdkPrintCommand):
name = 'spdk_print_bdevs'
def __init__(self):
bdevs = BdevMgrBdevs()
super(spdk_print_bdevs, self).__init__(self.name, bdevs)
class spdk_find_bdev(spdk_print_bdevs):
name = 'spdk_find_bdev'
def invoke(self, arg, from_tty):
print(arg)
bdev_query = [bdev for bdev in self.element_list
if str(bdev.get_name()).find(arg) != -1]
if bdev_query == []:
print("Cannot find bdev with name %s" % arg)
return
self.print_element_list(bdev_query)
class NvmfSubsystem(SpdkObject):
type_name = 'struct spdk_nvmf_subsystem'
def __init__(self, ptr):
self.ptr = ptr
gdb_obj = self.ptr.cast(gdb.lookup_type(self.type_name).pointer())
super(NvmfSubsystem, self).__init__(gdb_obj)
def get_name(self):
return self.obj['subnqn']
def get_id(self):
return int(self.obj['id'])
def get_ns_list(self):
max_nsid = int(self.obj['max_nsid'])
ns_list = []
for i in range(0, max_nsid):
nsptr = (self.obj['ns'] + i).dereference()
if nsptr == 0x0:
continue
ns = nsptr.cast(gdb.lookup_type('struct spdk_nvmf_ns').pointer())
ns_list.append(ns)
return ns_list
def __str__(self):
s = super(NvmfSubsystem, self).__str__()
s += '\nnqn %s' % self.get_name()
s += '\nID %d' % self.get_id()
for ns in self.get_ns_list():
s + '\t%s' % str(ns)
return s
class SpdkNvmfTgtSubsystems(SpdkArr):
def get_num_subsystems(self):
try: # version >= 18.11
return int(self.spdk_nvmf_tgt['max_subsystems'])
except RuntimeError: # version < 18.11
return int(self.spdk_nvmf_tgt['opts']['max_subsystems'])
def __init__(self):
self.spdk_nvmf_tgt = gdb.parse_and_eval("g_spdk_nvmf_tgt")
subsystems = gdb.parse_and_eval("g_spdk_nvmf_tgt->subsystems")
super(SpdkNvmfTgtSubsystems, self).__init__(subsystems,
self.get_num_subsystems(),
NvmfSubsystem)
class spdk_print_nvmf_subsystems(SpdkPrintCommand):
def __init__(self):
name = 'spdk_print_nvmf_subsystems'
nvmf_tgt_subsystems = SpdkNvmfTgtSubsystems()
super(spdk_print_nvmf_subsystems, self).__init__(name, nvmf_tgt_subsystems)
class IoChannel(SpdkObject):
type_name = 'struct spdk_io_channel'
def get_ref(self):
return int(self.obj['ref'])
def get_device(self):
return self.obj['dev']
def get_device_name(self):
return self.obj['dev']['name']
def get_name(self):
return ""
def __str__(self):
s = super(IoChannel, self).__str__() + '\n'
s += 'ref %d\n' % self.get_ref()
s += 'device %s (%s)\n' % (self.get_device(), self.get_device_name())
return s
# TODO - create TailqList type that gets a gdb object instead of a pointer
class IoChannels(SpdkTailqList):
def __init__(self, list_obj):
self.tailq_name_list = ['tailq']
self.list_member = IoChannel
self.list = list_obj
class SpdkThread(SpdkObject):
type_name = 'struct spdk_thread'
def __init__(self, gdb_obj):
super(SpdkThread, self).__init__(gdb_obj)
self.io_channels = IoChannels(self.obj['io_channels'])
def __str__(self):
s = super(SpdkThread, self).__str__() + '\n'
s += "IO Channels:\n"
for io_channel in self.get_io_channels():
channel_lines = str(io_channel).split('\n')
s += '\n'.join('\t%s' % line for line in channel_lines if line is not '')
s += '\n'
s += '\t---------------\n'
s += '\n'
return s
def get_io_channels(self):
return self.io_channels
class SpdkThreads(SpdkNormalTailqList):
def __init__(self):
super(SpdkThreads, self).__init__('g_threads', SpdkThread)
class spdk_print_threads(SpdkPrintCommand):
def __init__(self):
name = "spdk_print_threads"
threads = SpdkThreads()
super(spdk_print_threads, self).__init__(name, threads)
class spdk_load_macros(gdb.Command):
def __init__(self):
gdb.Command.__init__(self, 'spdk_load_macros',
gdb.COMMAND_DATA,
gdb.COMPLETE_SYMBOL,
True)
self.loaded = False
def invoke(self, arg, from_tty):
if arg == '--reload':
print('Reloading spdk information')
reload = True
else:
reload = False
if self.loaded and not reload:
return
spdk_print_threads()
spdk_print_bdevs()
spdk_print_io_devices()
spdk_print_nvmf_subsystems()
spdk_find_bdev()
spdk_load_macros()