Linux系统下 raid卡关机磁盘异响(直接断电)

@vrqq  June 5, 2024

虽然我的盘支持热插拔,但关机时的“直接断电”可能导致磁盘缓存未落盘。raid卡有电池,2盘同时离线时,盘上缓存的数据呢。
https://github.com/vrqq/megaspin

问题相关帖子

有关直接访问驱动器

但他们不解决我的问题,我的raid卡(/dev/sda) 在raid了下属硬盘之后,就不接受 STOP, STANDBY指令了

灵感解决方案

看了smartctl的代码 os_linux.cpp:linux_megaraid_device::megasas_cmd() 大受启发,我在这送一个SCSI STOP指令呢!
于是便有了如下关键代码

    uint8_t cmd_start[6] = {0x1b, 0x01, 0x00, 0x00, 0x01, 0x00};
    uint8_t cmd_stop[6]  = {0x1b, 0x01, 0x00, 0x00, 0x00, 0x00};
    // #define DXFER_NONE        0
    megasas_cmd(6, cmd_stop, 0, nullptr, 0, 0, 0, DXFER_NONE);

运行 果然停转!
之后卸载硬盘驱动 modprobe -r megaraid_sas,结果盘又转起来了!
于是考虑方案2 写一个假驱动放到关机脚本里 关机之前把这驱动上了!
修改思路1:扒linux kernel里面megaraid_sas的代码,然后构建通过ioctl传递的结构体,直接在.probe里面运行

下文开始从开始制作补丁
针对linux kernel 6.1所携带的megaraid_sas驱动以及相关工具已上传github
Warning: 由于不完整的shutdown和remove 可能含有大量对raid卡不正确的配置,只保证关机过程顺顺利利。

  1. 在当前操作系统中安装kernel-header和编译工具例如我是debian
    apt install build-essential linux-headers-`uname -r`
  2. 使用 uname -r查看当前内核版本,然后下载对应linux kernel source code
    例如我机器的执行结果为6.1.0-21-amd64,在 https://mirrors.edge.kernel.org/pub/ 找到如下文件
    https://mirrors.edge.kernel.org/pub/linux/kernel/v6.x/linux-6.1.tar.xz
    (.xz比.gz小了一半呢)
  3. 解压并把 linux-6.1/drivers/scsi/megaraid 里面的文件复制出来,鉴于我的raid卡比较新,没有保留_mbox, _mm结尾的文件,如有需要自行按照这个思路保留。
    然后修改Makefile如下:https://github.com/vrqq/megaspin/blob/master/drvspin/Makefile
  4. 在文件夹中 全文搜索module_init 找到kernel-module初始化代码。
    我这里在 megaraid_sas_base.c中搜索到了module_init(megasas_init);,在里面找到 pci_register_driver 这个结构体定义了“当驱动程序和硬件匹配到时,初始化硬件的驱动代码,以及卸载驱动的代码”

我这里的代码为

    /*
     * Register ourselves as PCI hotplug module
     */
    rval = pci_register_driver(&megasas_pci_driver);

沿着这里搜索 megasas_pci_driver 找到这个变量,修改probe, remove, shutdown对应的函数

/*
 * PCI hotplug support registration structure
 */
static struct pci_driver megasas_pci_driver = {

    .name = "megaraid_sas_spindown",
    .id_table = megasas_pci_table,
    .probe = megasas_probe_one,
    .remove = megasas_detach_one,
    .driver.pm = &megasas_pm_ops,
    .shutdown = megasas_shutdown,
};

注释megasas_probe_one()的如下代码,防止自动创建 /dev/sg0 以及 /dev/sda,拒绝某些小工具自动搜索scsi设备挂载

    /*
     * Trigger SCSI to scan our drives
     */
    // if (!instance->enable_fw_dev_list ||
    //     (instance->host_device_list_buf->count > 0))
    //     scsi_scan_host(host);

注释megasas_detach_one() 和 megasas_shutdown() 的如下代码,防止把控制权交还给raid卡固件,从而触发硬盘转起来

    // megasas_flush_cache(instance);
    // megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN);
  1. 修改驱动里面的名称 把megaraid_sas都替换成 megaraid_sas_spindown 放置重名,我这里有两处

    static struct pci_driver megasas_pci_driver = {
     .name = "megaraid_sas_spindown",
    }
    
    static struct scsi_host_template megasas_template = {
     .proc_name = "megaraid_sas_spindown",
    }
  2. 编译 运行

    # 驱动,卸载掉之前的以及挂载目前的
    root@debian:~/megaspin/drv_spin# make
    root@debian:~/megaspin/drv_spin# modprobe -r megaraid_sas
    root@debian:~/megaspin/drv_spin# insmod ./megaraid_sas_spindown.ko
    
    # GIT中控制盘的小工具 假设停转前3块盘
    root@debian:~/megaspin/scsi_cli# ./build.sh
    root@debian:~/megaspin/scsi_cli# ./megaio spindown 0 1 2
    
    # 测试 可发现 Kernel driver in use: megaraid_sas_spindown
    root@debian:~/megaspin/scsi_cli# lsmod |grep megaraid
    root@debian:~/megaspin/scsi_cli# lspci -vv
    
    # 测试关机也不会把控制权交还
    root@debian:~/megaspin/scsi_cli# shutdown -h now

    最后加入关机脚本

完整代码见GITHUB
https://github.com/vrqq/megaspin/tree/master
其中 drvspin 是驱动,scsi_cli是控制小工具

后记
正经的办法:给kernel提交个补丁,在/sys/.../drivers/ 里面新增属性 <phy_id>/disk_info 以及 <phy_id>/manage_power ,关机脚本中 读第一个值识别硬盘,写第二个值控制电源,可以兼容有内有外不同情况的盘柜。探索SAS3508 datasheet,找找有没有让盘停转且退出的指令,确保上述不发退出指令直接关机对raid卡是安全的。。

cons:老内核编译新模块可麻烦

REF: SCSI指令参考 https://www.seagate.com/files/staticfiles/support/docs/manual/Interface%20manuals/100293068j.pdf

常用脚本

查看smart参数
(目前只能看到raid卡下SATA盘的信息 SAS盘看不到)

# /dev/sda 是raid卡,0和1是卡下前两块盘
smartctl -d megaraid,0 -i -n standby /dev/sda
smartctl -d megaraid,1 -i -n standby /dev/sda

sdparm的用法以及SCSI介绍
https://diabloneo.github.io/2019/06/16/hdparm-and-sdparm/

# 查看支持的SCSI指令
sdparm --all --long /dev/sg0

# 查询VPD
sdparm --inquiry --all /dev/sg0

PCIE设备以及电源控制
https://www.kernel.org/doc/html/latest/PCI/sysfs-pci.html
https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-devices-power
https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-bus-pci
Linux PCI驱动框架分析 https://www.cnblogs.com/LoyenWang/p/14165852.html

# /sys/devices/.../power/wakeup : 是否允许该设备唤醒计算机
# 同windows设备管理器-设备属性-电源-允许该设备唤醒计算机 (Allow this device to wake the computer)
cat /sys/bus/pci/devices/0000:c1:00.0/power/wakeup

# /sys/devices/.../power/control : 允许计算机关闭这个设备的电源以省电
# 同windows设备管理器-设备属性-电源-允许该设备唤醒计算机 (Allow the computer to turn off the device to save power)
echo /sys/bus/pci/devices/0000:c1:00.0/power/control

# /sys/bus/pci/devices/.../remove : 实时移除硬件
# 执行后发现该设备从系统设备树中移出
echo 1 > /sys/bus/pci/devices/0000:c1:00.0/remove

# /sys/bus/pci/rescan : 重新搜索所有pci设备
# /sys/bus/pci/devices/.../rescan : 扫描检测硬件改动
echo 1 > /sys/bus/pci/rescan
echo 1 > /sys/bus/pci/devices/0000:c1:00.0/rescan

查看特定pcie设备参数

# 查看特定pcie设备参数 (此处为我的raid卡) 其支持 CAP_PM 如下
# Capabilities: [40] Power Management version 3
#                 Flags: PMEClk- DSI- D1+ D2+ AuxCurrent=0mA PME(D0-,D1-,D2-,D3hot-,D3cold-)
#                 Status: D0 NoSoftRst+ PME-Enable- DSel=0 DScale=0 PME-
lspci -s c1:00.0 -vv

向PCIE设备发送信息(写寄存器)

perccli用法

  • set offline所有硬盘 perccli64 /call /sall set offline

已有 13 条评论

  1. 《你知道,你的楼梯很漂亮》剧情片高清在线免费观看:https://www.jgz518.com/xingkong/63641.html

  2. 《弦动我心》剧情片高清在线免费观看:https://www.jgz518.com/xingkong/72551.html

  3. 《秘密绑架(加长版)》泰国剧高清在线免费观看:https://www.jgz518.com/xingkong/137018.html

  4. 《密爱七重奏》泰国剧高清在线免费观看:https://www.jgz518.com/xingkong/144550.html

  5. 真好呢

  6. 独家揭秘:传奇3私服火鸟逆天神力,震惊全服传奇爱好者!:https://501h.com/jingpin/2024-10-30/46000.html

  7. 想想你的文章写的特别好www.jiwenlaw.com

  8. 想想你的文章写的特别好https://www.ea55.com/

  9. 想想你的文章写的特别好https://www.237fa.com/

  10. aegfmj06842TR-文章很不错,感谢作者!https://kan.xiaoxinbk.com/57473.html/

  11. 博主真是太厉害了!!!

  12. cdsgg cdsgg

    博主有联系方式吗

添加新评论