def show_linear_lvm_uuid(dev): md, name = dev dm_table_map = StructResult("struct dm_table", md.map) for target_id in range(dm_table_map.num_targets): target = dm_table_map.targets.__getitem__(target_id) gendisk = StructResult("struct gendisk", md.disk) hash_cell = StructResult("struct hash_cell", md.interface_ptr) try: if ('LVM-' not in hash_cell.uuid): return except: pylog.warning("Invalid UUID for mapped_device:", hex(md), "| hash_cell.uuid (UUID) is:", hash_cell.uuid) return lv_uuid = hash_cell.uuid.partition("-") lv_uuid = lv_uuid[2] vg_lv_names = get_vg_lv_names(name) if ((vg_lv_names[0]) and (vg_lv_names[1])): lv_capacity = get_size(gendisk) print("dm-{:<10d} {:45s} {:20s} {:18.2f} {:10s} {:10s}\n". format(md.disk.first_minor, vg_lv_names[1], vg_lv_names[0], lv_capacity, lv_uuid[-32:], lv_uuid[:32]), end="")
def show_basic_mpath_info(dev): md, name = dev dm_table_map = StructResult("struct dm_table", md.map) mpath = StructResult("struct multipath", dm_table_map.targets.private) print("dm-{:<4d} {:<22} {:#x} ".format(md.disk.first_minor, name, mpath), end="") use_nr_paths_counter = -1 try: use_nr_paths_counter = readSU("struct multipath", long(mpath.nr_valid_paths.counter)) except: use_nr_paths_counter = -1 if (use_nr_paths_counter != -1): print("{:26d}".format(mpath.nr_valid_paths.counter), end="") else: print("{:26d}".format(mpath.nr_valid_paths), end="") if (member_size("struct multipath", "flags") != -1): if ((mpath.flags & (1 << 0)) or (mpath.flags & (1 << 1)) or (mpath.flags & (1 << 2))): print("\t\t{}".format("Enabled")) else: print("\t\t{}".format("Disabled")) else: if (mpath.queue_if_no_path): print("\t\t{}".format("Enabled")) else: print("\t\t{}".format("Disabled"))
def show_dmsetup_table_linear(dev): md, name = dev dm_table_map = StructResult("struct dm_table", md.map) for target_id in range(dm_table_map.num_targets): target = dm_table_map.targets.__getitem__(target_id) linear_c = StructResult("struct linear_c", target.private) print("{}: {} {} linear {}:{} [{}] {}".format( name, target.begin, target.len, linear_c.dev.bdev.bd_dev >> 20, linear_c.dev.bdev.bd_dev & 0xfffff, linear_c.dev.bdev.bd_disk.disk_name, linear_c.start))
def show_dmsetup_table_multipath(dev): md, name = dev dm_table_map = StructResult("struct dm_table", md.map) print("{}: {} {} multipath".format(name, dm_table_map.targets.begin, dm_table_map.targets.len), end="") mpath = StructResult("struct multipath", dm_table_map.targets.private) # general parameters params = [] if (member_size("struct multipath", "flags") != -1): if ((mpath.flags & (1 << 0)) or (mpath.flags & (1 << 1)) or (mpath.flags & (1 << 2))): params.append("queue_if_no_path") else: if (mpath.queue_if_no_path): params.append("queue_if_no_path") print(" {}".format(len(params)), end="") for param in params: print(" {}".format(param), end="") #hw handler parameters params = [] if (mpath.hw_handler_name): params.append(mpath.hw_handler_name) if (mpath.hw_handler_params): for param in mpath.hw_handler_params.split(" "): params.append(param) print(" {}".format(len(params)), end="") for param in params: print(" {}".format(param), end="") #number of path groups print(" {}".format(mpath.nr_priority_groups), end="") prio_groups = readSUListFromHead(mpath.priority_groups, "list", "struct priority_group") #next pathgroup to try if (mpath.current_pg): print(" {}".format(mpath.current_pg.pg_num), end="") elif (prio_groups): print(" {}".format(prio_groups[0].pg_num), end="") else: print(" 1", end="") for prio in prio_groups: show_table_mpath_priogroup(prio) print("")
def show_mpath_info(prio): for path in readSUListFromHead(prio.pgpaths, "list", "struct pgpath"): block_device = StructResult("struct block_device", path.path.dev.bdev) scsi_device = StructResult("struct scsi_device", block_device.bd_disk.queue.queuedata) print("\n `- {} {} {}:{} ".format( scsi_device.sdev_gendev.kobj.name, block_device.bd_disk.disk_name, block_device.bd_dev >> 20, block_device.bd_dev & 0xfffff), end="") enum_sdev_state = EnumInfo("enum scsi_device_state") if ('cciss' in block_device.bd_disk.disk_name): print("\t[Not a scsi device, skipping scsi_device struct!]", end="") else: print("\t[scsi_device: {:#x} sdev_state: {}]".format( scsi_device, enum_sdev_state.getnam(scsi_device.sdev_state)), end="")
def show_table_mpath_priogroup(prio): print(" {} 0 {} 1".format(prio.ps.type.name, prio.nr_pgpaths), end="") for path in readSUListFromHead(prio.pgpaths, "list", "struct pgpath"): path_info = StructResult("struct path_info", path.path.pscontext) print(" {}:{} [{}] {}".format(path.path.dev.bdev.bd_dev >> 20, path.path.dev.bdev.bd_dev & 0xfffff, path.path.dev.bdev.bd_disk.disk_name, path_info.repeat_count), end="")
def show_linear_lvm(dev): md, name = dev dm_table_map = StructResult("struct dm_table", md.map) for target_id in range(dm_table_map.num_targets): target = dm_table_map.targets.__getitem__(target_id) linear_c = StructResult("struct linear_c", target.private) gendisk = StructResult("struct gendisk", md.disk) pv_gendisk = StructResult("struct gendisk", linear_c.dev.bdev.bd_disk) hash_cell = StructResult("struct hash_cell", md.interface_ptr) try: if ('LVM-' not in hash_cell.uuid): return except: pylog.warning("Invalid UUID for mapped_device:", hex(md), "| hash_cell.uuid (UUID) is:", hash_cell.uuid) return vg_lv_names = get_vg_lv_names(name) if ((vg_lv_names[0]) and (vg_lv_names[1])): lv_capacity = get_size(gendisk) if ('dm-' in pv_gendisk.disk_name[:3]): pv_md, pv_md_name = get_md_mpath_from_gendisk(pv_gendisk) print("dm-{:<10d} {:45s} {:40s} " "{} {:18.2f} {}\t({})\n".format( md.disk.first_minor, vg_lv_names[1], vg_lv_names[0], md.open_count.counter, lv_capacity, pv_md_name, pv_gendisk.disk_name), end="") else: print("dm-{:<10d} {:45s} {:40s} " "{} {:18.2f} {}\n".format(md.disk.first_minor, vg_lv_names[1], vg_lv_names[0], md.open_count.counter, lv_capacity, pv_gendisk.disk_name), end="")
def show_linear_lvm_pv(dev): md, name = dev dm_table_map = StructResult("struct dm_table", md.map) for target_id in range(dm_table_map.num_targets): target = dm_table_map.targets.__getitem__(target_id) linear_c = StructResult("struct linear_c", target.private) gendisk = StructResult("struct gendisk", md.disk) pv_gendisk = StructResult("struct gendisk", linear_c.dev.bdev.bd_disk) hash_cell = StructResult("struct hash_cell", md.interface_ptr) try: if ('LVM-' not in hash_cell.uuid): return except: pylog.warning("Invalid UUID for mapped_device:", hex(md), "| hash_cell.uuid (UUID) is:", hash_cell.uuid) return vg_lv_names = get_vg_lv_names(name) if ((vg_lv_names[0]) and (vg_lv_names[1])): pv_capacity = get_size(pv_gendisk) if ('dm-' in pv_gendisk.disk_name[:3]): pv_md, pv_md_name = get_md_mpath_from_gendisk(pv_gendisk) print("{} ({})\t{:18} {:30x}\t {:32.2f}\t" "{:20s} {}\n".format(pv_md_name, pv_gendisk.disk_name, "", pv_md, pv_capacity, vg_lv_names[0], vg_lv_names[1]), end="") else: print("{:45s} {}\t {:25.2f}\t" "{:20s} {}\n".format(pv_gendisk.disk_name, "[PV not on dm dev, skipping!]", pv_capacity, vg_lv_names[0], vg_lv_names[1]), end="")
def run_check_on_multipath(): tt = TaskTable() bts = [] errors = 0 task_cnt = 0 multipathd_daemon = 0 # To verify if multipathd daemon is running multipath_blocked = 0 # To verify if multipathd daemon or command is blocked mpath_present = 0 # To verify if multipath device exists with or without # multipathd daemon running wq_blocked = 0 # To verify if scsi_wq or fc_wq is blocked kworker_md_blocked = 0 # Counter for hung worker threads which are waiting for # IO requests on mdraid devices print("\nChecking for device-mapper issues...\n") for t in tt.allThreads(): print("Getting a list of processes in UN state..." "(Count: {:d})".format(task_cnt), end="\r") if ('multipathd' in t.comm): multipathd_daemon = 1 if (t.ts.state & TASK_STATE.TASK_UNINTERRUPTIBLE): task_cnt += 1 # crash can miss some threads when there are pages missing # and it will not do 'bt' in that case. try: bts.append(exec_bt("bt %d" % t.pid)[0]) except: pass print("Getting a list of processes in UN state...\t\t\t[Done]") if (task_cnt): print("\nProcessing the back trace of hung tasks...\t\t\t", end='') for bt in bts: if ('kworker' in bt.cmd): if (bt.hasfunc('md_flush_request') and bt.hasfunc('dio_aio_complete_work')): kworker_md_blocked += 1 if ('multipath' in bt.cmd): multipath_blocked = 1 if (('scsi_wq' in bt.cmd) or ('fc_wq' in bt.cmd)): wq_blocked = 1 print("[Done]") # Checks for dm devices for dev in devlist: md, name = dev dm_table_map = StructResult("struct dm_table", md.map) # Check if there is any multipath device present in device-mapper table if (dm_table_map.targets.type.name == "multipath"): mpath_present += 1 # Check if kworker threads are stuck waiting to flush IO on mdraid devices if (kworker_md_blocked >= 5): print( "\n ** {} kworker threads are stuck in UN state waiting to flush the IO" "\n requests on mdraid devices. This could be a result of thundering" "\n herd problem. See reference: " "\n https://marc.info/?l=linux-raid&m=155364683109115&w=2". format(kworker_md_blocked)) print( "\n Run 'hanginfo' for more information on processes in UN state." ) errors += 1 # multipath devices are present but multipathd is not running if (mpath_present != 0 and multipathd_daemon == 0): print( "\n ** multipath device(s) are present, but multipathd service is" "\n not running. IO failover/failback may not work.") errors += 1 # scsi or fc work queue and multipathd are blocked if (multipath_blocked == 1 and wq_blocked == 1): print( "\n ** multipathd and scsi/fc work_queue processes are stuck in UN state," "\n this could block IO failover on multipath devices") print( "\n Run 'hanginfo' for more information on processes in UN state." ) errors += 1 # only multipathd process is stuck in UN state elif (multipath_blocked == 1): print("\n ** multipathd processes stuck in UN state," "\n this could block IO failover on multipath devices") print( "\n Run 'hanginfo' for more information on processes in UN state." ) errors += 1 if (errors == 0 and task_cnt != 0): print("\n No device-mapper, multipath issues detected by utility," "\n but found {} processes in UN state.".format(task_cnt)) print( "\n Run 'hanginfo' for more information on processes in UN state." ) elif (errors == 0 and task_cnt == 0): print("No issues detected by utility.")
def get_md_mpath_from_gendisk(pv_gendisk): tmp_mapped_device = StructResult("struct mapped_device", pv_gendisk.queue.queuedata) for temp_dev in devlist: if (tmp_mapped_device == temp_dev[0]): return temp_dev
def show_multipath_list(dev): md, name = dev dm_table_map = StructResult("struct dm_table", md.map) print( "------------------------------------------------------------------------------------------" ) mpath = StructResult("struct multipath", dm_table_map.targets.private) prio_groups = readSUListFromHead(mpath.priority_groups, "list", "struct priority_group") temp_prio_groups_list = readSU("struct list_head", mpath.priority_groups) temp_priority_group = StructResult("struct priority_group", temp_prio_groups_list.next) temp_pgpath_list = readSU("struct list_head", temp_priority_group.pgpaths) temp_pgpath = StructResult("struct pgpath", temp_pgpath_list.next) try: temp_scsi_device = StructResult( "struct scsi_device", temp_pgpath.path.dev.bdev.bd_disk.queue.queuedata) except: pylog.warning("Error in processing sub paths for multipath device:", name) pylog.warning( "Use 'dmshow --table|grep <mpath-device-name>' to manually verify sub paths." ) return hash_cell = StructResult("struct hash_cell", md.interface_ptr) scsi_id = hash_cell.uuid scsi_id = scsi_id.partition("-") if ('cciss' in temp_pgpath.path.dev.bdev.bd_disk.disk_name): print("{} ({}) dm-{:<4d} HP Smart Array RAID Device (cciss)".format( name, scsi_id[2], md.disk.first_minor), end="") else: print("{} ({}) dm-{:<4d} {} {}".format( name, scsi_id[2], md.disk.first_minor, temp_scsi_device.vendor[:8], temp_scsi_device.model[:16]), end="") print("\nsize={:.2f}M ".format(get_size( temp_pgpath.path.dev.bdev.bd_disk)), end="") if (member_size("struct multipath", "flags") != -1): if ((mpath.flags & (1 << 0)) or (mpath.flags & (1 << 1)) or (mpath.flags & (1 << 2))): print("(queue_if_no_path enabled) ".format(), end="") else: print("(queue_if_no_path disabled) ".format(), end="") else: if (mpath.queue_if_no_path): print("features='1 queue_if_no_path' ".format(), end="") else: print("features='0' (queue_if_no_path disabled) ".format(), end="") if (mpath.hw_handler_name): print("hwhandler={} hwhandler params={} ".format( mpath.hw_handler_name, mpath.hw_handler_params), end="") else: print("hwhandler={} ".format(mpath.hw_handler_name), end="") for prio in prio_groups: print("\n+- policy='{}' ".format(prio.ps.type.name), end="") show_mpath_info(prio) print("")
"VG UUID")) elif (args.pvs): print("{:45s} {:40s}\t {}\t{:20s} {}\n".format( "PV NAME", "PV's MAPPED_DEVICE", "DEVICE SIZE (MB)", "VG NAME", "LV NAME"), end="") elif (args.table): pass else: print("NUMBER NAME MAPPED_DEVICE FIELDS") mpathfound = 0 for dev in devlist: md, name = dev dm_table_map = StructResult("struct dm_table", md.map) if (args.multipath): if (not (dm_table_map.targets.type.name == "multipath")): continue show_basic_mpath_info(dev) mpathfound = 1 elif (args.multipathlist): if (not (dm_table_map.targets.type.name == "multipath")): continue show_multipath_list(dev) mpathfound = 1 elif (args.lvs): if (dm_table_map.targets.type.name == "linear"): show_linear_lvm(dev)
def run_scsi_checks(): warnings = 0 errors = 0 use_atomic_counters = -1 gendev_q_sdev_q_mismatch = 0 retry_delay_bug = 0 qla_cmd_abort_bug = 0 jiffies = readSymbol("jiffies") # host checks hosts = get_scsi_hosts() try: use_atomic_counters = readSU("struct Scsi_Host", long(hosts[0].host_busy.counter)) except: use_atomic_counters = -1 for host in hosts: if (use_atomic_counters == -1): if (host.host_failed): warnings += 1 if (host.host_failed == host.host_busy): print( "WARNING: Scsi_Host {:#x} ({}) is running error recovery!" .format(host, host.shost_gendev.kobj.name)) else: print( "WARNING: Scsi_Host {:#x} ({}) has timed out commands, but has not started error recovery!" .format(host, host.shost_gendev.kobj.name)) if (host.host_blocked): warnings += 1 print( "WARNING: Scsi_Host {:#x} ({}) is blocked! HBA driver refusing all commands with SCSI_MLQUEUE_HOST_BUSY?" .format(host, host.shost_gendev.kobj.name)) elif (use_atomic_counters != -1): if (host.host_failed): warnings += 1 if (host.host_failed == host.host_busy.counter): print( "WARNING: Scsi_Host {:#x} ({}) is running error recovery!" .format(host, host.shost_gendev.kobj.name)) else: print( "WARNING: Scsi_Host {:#x} ({}) has timed out commands, but has not started error recovery!" .format(host, host.shost_gendev.kobj.name)) if (host.host_blocked.counter): warnings += 1 print( "WARNING: Scsi_Host {:#x} ({}) is blocked! HBA driver refusing all commands with SCSI_MLQUEUE_HOST_BUSY?" .format(host, host.shost_gendev.kobj.name)) # device checks gendev_dict = get_gendev() for sdev in get_SCSI_devices(): if (use_atomic_counters == -1): if (sdev.device_blocked): warnings += 1 print( "WARNING: scsi_device {:#x} ({}) is blocked! HBA driver returning " "SCSI_MLQUEUE_DEVICE_BUSY or device returning SAM_STAT_BUSY?" .format(sdev, get_scsi_device_id(sdev))) if (sdev.device_busy < 0): print( "ERROR: scsi_device {:#x} ({}) device_busy count is: {}". format(sdev, get_scsi_device_id(sdev), sdev.device_busy)) if (sdev.host.hostt.name in "qla2xxx"): qla_cmd_abort_bug += 1 elif (use_atomic_counters != -1): if (sdev.device_blocked.counter): warnings += 1 print( "WARNING: scsi_device {:#x} ({}) is blocked! HBA driver returning " "SCSI_MLQUEUE_DEVICE_BUSY or device returning SAM_STAT_BUSY?" .format(sdev, get_scsi_device_id(sdev))) if (sdev.device_busy.counter < 0): print( "ERROR: scsi_device {:#x} ({}) device_busy count is: {}". format(sdev, get_scsi_device_id(sdev), sdev.device_busy.counter)) if (sdev.host.hostt.name in "qla2xxx"): qla_cmd_abort_bug += 1 # Check if scsi_device->request_queue is same as corresponding gendisk->queue. name = scsi_device_type(sdev.type) if (name): if (name in 'Direct-Access '): sdev_q = StructResult("struct request_queue", sdev.request_queue) sdev_q = format(sdev_q, 'x') try: gendev = gendev_dict[sdev_q] except: gendev_q_sdev_q_mismatch += 1 # Checks for qla2xxx bug for retry_delay RH BZ#1588133 if (sdev.host.hostt.name in "qla2xxx" and (member_size("struct fc_port", "retry_delay_timestamp") != -1)): fc_port = readSU("struct fc_port", long(sdev.hostdata)) retry_delay_timestamp = readSU("struct fc_port", long(fc_port.retry_delay_timestamp)) if (retry_delay_timestamp != 0): retry_delay = (retry_delay_timestamp - jiffies) / 1000 / 60 if (retry_delay > 2): errors += 1 print( "ERROR: scsi_device {:#x} ({}) has retry_delay_timestamp: {:d}, " "IOs delayed for {:f} more minutes".format( sdev, get_scsi_device_id(sdev), retry_delay_timestamp, retry_delay)) retry_delay_bug += 1 # command checks for cmnd in get_scsi_commands(sdev): try: timeout = cmnd.request.timeout except KeyError: timeout = 0 if (not timeout): try: timeout = cmnd.timeout_per_command except KeyError: print("Error: cannot determine timeout!") # Check for large timeout values if (timeout > 300000): errors += 1 print( "ERROR: scsi_cmnd {:#x} on scsi_device {:#x} ({}) has a huge timeout of {}ms!" .format(cmnd, cmnd.device, get_scsi_device_id(cmnd.device), timeout)) elif (timeout == 300000): warnings += 1 print( "WARNING: 5 minute timeout found for scsi_cmnd {:#x}! on scsi_device {:#x} ({}) " "Update device-mapper-multipath?".format( cmnd, cmnd.device, get_scsi_device_id(cmnd.device))) elif (timeout > 60000): warnings += 1 print( "WARNING: scsi_cmnd {:#x} on scsi_device {:#x} ({}) has a large timeout of {}ms." .format(cmnd, cmnd.device, get_scsi_device_id(cmnd.device), timeout)) # check for old command if (timeout and jiffies > (timeout + cmnd.jiffies_at_alloc)): print( "Warning: scsi_cmnd {:#x} on scsi_device {:#x} ({}) older than its timeout: " "EH or stalled queue?".format( cmnd, cmnd.device, get_scsi_device_id(cmnd.device))) warnings += 1 # scsi_target checks stgt_busy_block_cnt = -1 for shost in get_scsi_hosts(): if (shost.__targets.next != shost.__targets.next.next): for starget in readSUListFromHead(shost.__targets, "siblings", "struct scsi_target"): if (member_size("struct scsi_target", "target_busy") != -1): try: stgt_busy_block_cnt = readSU( "struct scsi_target", long(starget.target_busy.counter)) except: stgt_busy_block_cnt = -1 try: if (stgt_busy_block_cnt != -1): if (starget.target_busy.counter > 0): print( "WARNING: scsi_target {:10s} {:x} is having non-zero " "target_busy count: {:d}".format( starget.dev.kobj.name, int(starget), starget.target_busy.counter)) warnings += 1 if (starget.target_blocked.counter > 0): print( "WARNING: scsi_target {:10s} {:x} is blocked " "(target_blocked count: {:d})".format( starget.dev.kobj.name, int(starget), starget.target_blocked.counter)) warnings += 1 elif (stgt_busy_block_cnt == -1 and member_size( "struct scsi_target", "target_busy") != -1): if (starget.target_busy > 0): print( "WARNING: scsi_target {:10s} {:x} is having non-zero " "target_busy count: {:d}".format( starget.dev.kobj.name, int(starget), starget.target_busy)) warnings += 1 if (starget.target_blocked > 0): print( "WARNING: scsi_target {:10s} {:x} is blocked " "(target_blocked count: {:d})".format( starget.dev.kobj.name, int(starget), starget.target_blocked)) warnings += 1 except KeyError: pylog.warning("Error in processing scsi_target {:x}," "please check manually".format( int(starget))) if (retry_delay_bug): print( "\t HBA driver returning 'SCSI_MLQUEUE_TARGET_BUSY' due to a large retry_delay.\n" "\t See https://patchwork.kernel.org/patch/10450567/") if (qla_cmd_abort_bug): print( "\t scsi_device.device_busy count is negative, this could be caused due to" " double completion of scsi_cmnd from qla2xxx_eh_abort.\n" "\t See https://patchwork.kernel.org/patch/10587997/") if (gendev_q_sdev_q_mismatch != 0): print( "\n\tNOTE: The scsi_device->request_queue is not same as gendisk->request_queue\n" "\t for {} scsi device(s). \n\n" "\t It is likely that custom multipathing solutions have created 'gendisk',\n" "\t 'request_queue' structures which are not registered with kernel.\n" "\t *Although this may or may not be a reason for issue, but it could make\n" "\t the analysis of scsi_device, request_queue and gendisk struct confusing!\n" .format(gendev_q_sdev_q_mismatch)) if (not (warnings or errors or gendev_q_sdev_q_mismatch)): print("Nothing found")
def print_request_queue(): counter = 0 cmnd_requests = [] gendev_dict = get_gendev() jiffies = readSymbol("jiffies") opcode_table = {'0x00':'TUR', '0x03':'REQ-SENSE', '0x08':'READ(6)',\ '0x0a':'WRITE(6)', '0x12':'INQUIRY', '0x16':'RESERVE(6)',\ '0x17':'RELEASE(6)', '0x25':'READ-CAP(10)', '0x28':'READ(10)',\ '0x2a':'WRITE(10)', '0x41':'WR SAME', '0x56':'RESERVE(10)',\ '0x57':'RELEASE(10)', '0x88':'READ(16)', '0x8a':'WRITE(16)',\ '0xa0':'REPORT LUNS', '0xa8':'READ(12)', '0xaa':'WRITE (12)'} for sdev in get_SCSI_devices(): name = scsi_device_type(sdev.type) if (name): if ((name in 'Direct-Access ') or (name in 'CD-ROM ')): sdev_q = StructResult("struct request_queue", sdev.request_queue) if (member_size("struct elevator_queue", "elevator_type") != -1): elevator_name = sdev_q.elevator.elevator_type.elevator_name elif (member_size("struct elevator_queue", "type") != -1): elevator_name = sdev_q.elevator.type.elevator_name else: elevator_name = "<Unknown>" sdev_q = format(sdev_q, 'x') try: gendev = gendev_dict[sdev_q] gendev = readSU("struct gendisk", long(gendev, 16)) name = gendev.disk_name except: name = "Disk" print( "\n===========================================================" "============================================================" ) print(" ### DEVICE : {}\n".format(name)) print( " ----------------------------------------------------" "-----------------------------------") if (name == "Disk"): print("\tgendisk \t: {} |" "\tscsi_device \t: {:x}".format( "<Can't find gendisk>", int(sdev))) else: print( "\tgendisk \t: {:x}\t|\tscsi_device \t: {:x}". format(int(gendev), int(sdev))) print("\trequest_queue \t: {}\t|\tH:C:T:L \t: {}". format(sdev_q, sdev.sdev_gendev.kobj.name)) print( "\televator_name \t: {} \t\t|\tVENDOR/MODEL\t: {} {}" .format(elevator_name, sdev.vendor[:8], sdev.model[:16])) print( " ----------------------------------------------------" "-----------------------------------") cmnd_requests = [] cmnds = get_scsi_commands(sdev) for cmnd in cmnds: cmnd_requests.append(cmnd.request) requests = get_queue_requests(sdev.request_queue) requests = list(set(requests + cmnd_requests)) print("\n {:10s}{:20s} {:20s} {:18s} {:10s} {:20s} {:10s}". format("NO.", "request", "bio", "scsi_cmnd", "OPCODE", "COMMAND AGE", "SECTOR")) print( " -------------------------------------------------------" "------------------------------------------------------") counter = 0 for req in requests: counter = counter + 1 cmnd = StructResult("struct scsi_cmnd", req.special) try: time = (long(jiffies) - long(cmnd.jiffies_at_alloc)) opcode = StructResult("struct scsi_cmnd", long(cmnd.cmnd[0])) opcode = hex(opcode) try: opcode = opcode_table[opcode] except: pass print( " {:3d} {:3s} {:18x} {:20x} {:20x} {:10} {:8d} ms " .format(counter, "", req, req.bio, cmnd, opcode, long(time)), end="") if (req.bio): print("{:15d}".format(req.bio.bi_sector)) else: print(" ---NA---") except: pylog.warning("Invalid scsi_cmnd address in request: ", name, req, cmnd) if (counter == 0): print("\t\t<<< NO I/O REQUESTS FOUND ON THE DEVICE! >>>")
def print_sdev_shost(): enum_sdev_state = EnumInfo("enum scsi_device_state") gendev_dict = get_gendev() for shost in get_scsi_hosts(): if (shost.__devices.next != shost.__devices.next.next): print( "\n==============================================================================" "===============================================================================" ) print("HOST DRIVER") print( "NAME NAME {:24s} {:24s} {:24s}" .format("Scsi_Host", "shost_data", "&.hostdata[0]", end="")) print("--------------------------------------------------------" "-------------------------------------------------------") print_shost_header(shost) print("{:17s} {:23s} {:16s} {:25s} {:24s} {} {} {}" "\n".format("DEV NAME", "scsi_device", "H:C:T:L", "VENDOR/MODEL", "DEVICE STATE", "IOREQ-CNT", "IODONE-CNT", " IOERR-CNT"), end="") print("-----------------------------------------------------" "-----------------------------------------------------" "---------------------------------------------------") for sdev in readSUListFromHead(shost.__devices, "siblings", "struct scsi_device"): name = scsi_device_type(sdev.type) if (name): if (name in 'Sequential-Access'): name = "Tape" elif (name in 'Medium Changer '): name = "Chngr" elif (name in 'RAID '): name = "CTRL" elif ((name in 'Direct-Access ') or (name in 'CD-ROM ')): sdev_q = StructResult("struct request_queue", sdev.request_queue) sdev_q = format(sdev_q, 'x') try: gendev = gendev_dict[sdev_q] gendev = readSU("struct gendisk", long(gendev, 16)) name = gendev.disk_name except: name = "Disk" else: name = "null" print("{:17s} {:x} {:6s} {:16} {} {} {:22s}" "{:14d} {:11} ({:3d})\t{:10d}\n".format( name, int(sdev), "", get_scsi_device_id(sdev), sdev.vendor[:8], sdev.model[:16], get_sdev_state( enum_sdev_state.getnam(sdev.sdev_state)), sdev.iorequest_cnt.counter, sdev.iodone_cnt.counter, sdev.iorequest_cnt.counter - sdev.iodone_cnt.counter, sdev.ioerr_cnt.counter), end='')