2019-01-28 14:33:46 +00:00
|
|
|
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):
|
2019-02-13 15:18:38 +00:00
|
|
|
for i in range(0, self.num_elements):
|
2019-01-28 14:33:46 +00:00
|
|
|
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 = []
|
2019-02-13 15:18:38 +00:00
|
|
|
for i in range(0, max_nsid):
|
2019-01-28 14:33:46 +00:00
|
|
|
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()
|
|
|
|
|
2019-02-13 17:06:22 +00:00
|
|
|
|
2019-01-28 14:33:46 +00:00
|
|
|
spdk_load_macros()
|