Linux 开启 SCSI 日志调试功能

Linux 开启 SCSI 日志调试功能

1.编译选项中需开启 CONFIG_SCSI_LOGGING

2.该编译选项说明:drivers/scsi/Kconfig:213

config SCSI_LOGGING
    bool "SCSI logging facility"
    depends on SCSI
    ---help---
      This turns on a logging facility that can be used to debug a number
      of SCSI related problems.

      If you say Y here, no logging output will appear by default, but you
      can enable logging by saying Y to "/proc file system support" and
      "Sysctl support" below and executing the command

      echo <bitmask> > /proc/sys/dev/scsi/logging_level

      where <bitmask> is a four byte value representing the logging type
      and logging level for each type of logging selected.

      There are a number of logging types and you can find them in the
      source at <file:drivers/scsi/scsi_logging.h>. The logging levels
      are also described in that file and they determine the verbosity of
      the logging for each logging type.

      If you say N here, it may be harder to track down some types of SCSI
      problems. If you say Y here your kernel will be somewhat larger, but
      there should be no noticeable performance impact as long as you have
      logging turned off.

3.logging 类型源码文件位置(有说明) -> drivers\scsi\scsi_logging.h

#define SCSI_LOG_ERROR_SHIFT              0
#define SCSI_LOG_TIMEOUT_SHIFT            3
#define SCSI_LOG_SCAN_SHIFT               6
#define SCSI_LOG_MLQUEUE_SHIFT            9
#define SCSI_LOG_MLCOMPLETE_SHIFT         12
#define SCSI_LOG_LLQUEUE_SHIFT            15
#define SCSI_LOG_LLCOMPLETE_SHIFT         18
#define SCSI_LOG_HLQUEUE_SHIFT            21
#define SCSI_LOG_HLCOMPLETE_SHIFT         24
#define SCSI_LOG_IOCTL_SHIFT              27

#define SCSI_LOG_ERROR_BITS               3
#define SCSI_LOG_TIMEOUT_BITS             3
#define SCSI_LOG_SCAN_BITS                3
#define SCSI_LOG_MLQUEUE_BITS             3
#define SCSI_LOG_MLCOMPLETE_BITS          3
#define SCSI_LOG_LLQUEUE_BITS             3
#define SCSI_LOG_LLCOMPLETE_BITS          3
#define SCSI_LOG_HLQUEUE_BITS             3
#define SCSI_LOG_HLCOMPLETE_BITS          3
#define SCSI_LOG_IOCTL_BITS               3

#define SCSI_LOG_ERROR_RECOVERY(LEVEL,CMD)  \
        SCSI_CHECK_LOGGING(SCSI_LOG_ERROR_SHIFT, SCSI_LOG_ERROR_BITS, LEVEL,CMD);
#define SCSI_LOG_TIMEOUT(LEVEL,CMD)  \
        SCSI_CHECK_LOGGING(SCSI_LOG_TIMEOUT_SHIFT, SCSI_LOG_TIMEOUT_BITS, LEVEL,CMD);
#define SCSI_LOG_SCAN_BUS(LEVEL,CMD)  \
        SCSI_CHECK_LOGGING(SCSI_LOG_SCAN_SHIFT, SCSI_LOG_SCAN_BITS, LEVEL,CMD);
#define SCSI_LOG_MLQUEUE(LEVEL,CMD)  \
        SCSI_CHECK_LOGGING(SCSI_LOG_MLQUEUE_SHIFT, SCSI_LOG_MLQUEUE_BITS, LEVEL,CMD);
#define SCSI_LOG_MLCOMPLETE(LEVEL,CMD)  \
        SCSI_CHECK_LOGGING(SCSI_LOG_MLCOMPLETE_SHIFT, SCSI_LOG_MLCOMPLETE_BITS, LEVEL,CMD);
#define SCSI_LOG_LLQUEUE(LEVEL,CMD)  \
        SCSI_CHECK_LOGGING(SCSI_LOG_LLQUEUE_SHIFT, SCSI_LOG_LLQUEUE_BITS, LEVEL,CMD);
#define SCSI_LOG_LLCOMPLETE(LEVEL,CMD)  \
        SCSI_CHECK_LOGGING(SCSI_LOG_LLCOMPLETE_SHIFT, SCSI_LOG_LLCOMPLETE_BITS, LEVEL,CMD);
#define SCSI_LOG_HLQUEUE(LEVEL,CMD)  \
        SCSI_CHECK_LOGGING(SCSI_LOG_HLQUEUE_SHIFT, SCSI_LOG_HLQUEUE_BITS, LEVEL,CMD);
#define SCSI_LOG_HLCOMPLETE(LEVEL,CMD)  \
        SCSI_CHECK_LOGGING(SCSI_LOG_HLCOMPLETE_SHIFT, SCSI_LOG_HLCOMPLETE_BITS, LEVEL,CMD);
#define SCSI_LOG_IOCTL(LEVEL,CMD)  \
        SCSI_CHECK_LOGGING(SCSI_LOG_IOCTL_SHIFT, SCSI_LOG_IOCTL_BITS, LEVEL,CMD);

4.使用说明

/*
 * Note - the initial logging level can be set here to log events at boot time.
 * After the system is up, you may enable logging via the /proc interface.
 */
unsigned int scsi_logging_level;
#if defined(CONFIG_SCSI_LOGGING)
EXPORT_SYMBOL(scsi_logging_level);
#endif

scsi_logging_level 被定义成int类型(32bit),该机制使用了30个bit,从低位到高位每3bit为一个logging level从SCSI_LOG_ERROR_SHIFT到SCSI_LOG_IOCTL_SHIFT(SCSI_LOG_XXX_SHIFT为不同level的移位数),每个level使用的bit数都是3,所以 SCSI_LOG_XXX_BITS 均为3

举例:

drivers/scsi/sd.c sd_probe()函数中:

SCSI_LOG_IOCTL(1, sd_printk(KERN_INFO, sdkp, "sd_ioctl: disk=%s, "
                    "cmd=0x%x\n", disk->disk_name, cmd));

#define SCSI_LOG_IOCTL(LEVEL,CMD)  \
        SCSI_CHECK_LOGGING(SCSI_LOG_IOCTL_SHIFT, SCSI_LOG_IOCTL_BITS, LEVEL,CMD);

#define SCSI_LOG_IOCTL_SHIFT              27
#define SCSI_LOG_IOCTL_BITS               3

#ifdef CONFIG_SCSI_LOGGING                // 编译选项已开启

#define SCSI_LOG_LEVEL(SHIFT, BITS)             \
        ((scsi_logging_level >> (SHIFT)) & ((1 << (BITS)) - 1))        

#define SCSI_CHECK_LOGGING(SHIFT, BITS, LEVEL, CMD)     \
do {                                \
        if (unlikely((SCSI_LOG_LEVEL(SHIFT, BITS)) > (LEVEL)))  \
        do {                        \
            CMD;                    \
        } while (0);                    \
} while (0)
#else
#define SCSI_LOG_LEVEL(SHIFT, BITS) 0
#define SCSI_CHECK_LOGGING(SHIFT, BITS, LEVEL, CMD)
#endif /* CONFIG_SCSI_LOGGING */

在宏 SCSI_LOG_LEVEL 中生成一个LOG_LEVEL值与LEVEL比较
((scsi_logging_level >> (27)) & ((1 << (3)) - 1))
只取 scsi_logging_level 的第28-30bit,与0x3相与,若 SCSI_LOG_LEVEL 结果大于 LEVEL,则 CMD 被执行,即 sd_probe 中 SCSI_LOG_IOCTL 第二个参数

sd_printk(KERN_INFO, sdkp, “sd_ioctl: disk=%s, ”
“cmd=0x%x\n”, disk->disk_name, cmd)

会被执行。

5.scsi_logging_level 值可以在 boot 命令行设置也可以开启设备后在 /proc 文件系统中设置:

-1   - Enable scsi events to syslog.         // 开启所有scsi log
0    - Disable scsi events to syslog.        // 关闭所有scsi log

命令:
    echo 0/-1 > /proc/sys/dev/scsi/logging_level
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值