diff options
Diffstat (limited to 'src/spdk/scripts/gdb_macros.py')
-rw-r--r-- | src/spdk/scripts/gdb_macros.py | 289 |
1 files changed, 289 insertions, 0 deletions
diff --git a/src/spdk/scripts/gdb_macros.py b/src/spdk/scripts/gdb_macros.py new file mode 100644 index 000000000..74234de7b --- /dev/null +++ b/src/spdk/scripts/gdb_macros.py @@ -0,0 +1,289 @@ +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() |