使用 SystemTap 进行 I/O 错误注入

最近一直沉迷于折腾各种错误注入,总想着把我们的系统给搞挂,有一天,突发奇想,是不是能通过 SystemTap 来捣乱,因为 SystemTap 能 probe 相关的函数,那么我们就一定能在这些 probe 里面干一些事情,想到这里,立刻激动不已,直接 Google 了一下,发现业界早就有这么做的先例,这能说自己太 out 了。

SCSI Fault Injection

Google 搜出来提到最多的就是 SCSI Fault Injection Test 这篇 Paper,里面提到了用 SystemTap 在 SCSI 这一层对 I/O 进行注入,当即我就非常的兴奋,毕竟我一直在思考一个好的办法对 TiKV 存储的数据进行干扰,譬如写一块数据进去的时候,把这些数据直接改掉,或者读文件的时候随机的报错这些。但悲催的是,这篇文件使用的 kernel 已经非常的老了,在 CentOS 7 下面根本就跑不了。幸好,原理还是很好理解,所以对着新的内核稍微调整一下就行了。在继续之前,先来聊聊,为什么这篇文章的作者想用 SystemTap 在 SCSI 这层注入错误。

大家都知道,当我们在处理 I/O 的时候,会面临各种这样的错误,但如何在程序里面模拟这些错误,其实是一件比较困难的事情。通常的做法就是写一个 mock IO,但这个仅仅只能用于 unit test,而且完全模拟所有的错误其实也不现实,过度追求 coverage,会导致整个的 test 代码极度的膨胀。我们其实更希望的是,在程序正常运行的过程中,模拟很多错误,来观察程序在这些错误情况下面的反映。因为我们要注入 I/O 错误,在 Linux 系统里面,SCSI 作为一个通用的 driver,对其进行注入就非常的合适了。

对于一个 SCSI 故障来说,通常有两种,一个就是 SCSI 的设备返回了一个错误,而另一个就是 SCSI 的设备没有任何返回,超时了。对于底层硬件设备(譬如 HDD)来说,通常也是两种故障,临时的(可恢复)和永久的(不可恢复)。根据上面的情况,我们有多种组合:

  • 临时的读错误
  • 临时的写错误
  • 能被后续的写覆盖修复的读错误,这种的本来读是错了,后面的写能够覆盖,这样后面的读还是能读到最新的写入数据
  • 永久的读错误,不同于上面可被写覆盖修复的读错误,这里的任何读都会失败,但写有可能不会,因为一些硬件不会去进行写错误检查
  • 永久的读写错误
  • 临时的读超时
  • 临时的写超时
  • 永久的读写超时

可以看到,如果我们需要模拟上面这么多种组合,其实是比较困难的,业界有一些办法,但都有局限性,譬如:

  • Linux 的 scsi_debug driver, 它提供了一个模拟的 SCSI 设备,但还是有一些局限性,譬如对于一些访问注入错误,只能通过 sector 0x1234 来进行。
  • Linux 的 Fault Injection 框架,这个是 kernel 原生支持的,但也有一些局限,譬如不能提供 SCSI 的设备 timeout,另外,这个功能需要重新编译 kernel 去支持,并不通用。
  • 使用特定的设备,这个就不说了,更加不通用了。

所以,论文的作者使用了 SystemTap 来进行。这里我不详细的说明论文里面 SCSI 的整个工作流程,主要是因为论文里面使用的内核版本比较低,我现在也不知道最新的内核的工作流程了。但对于 SystemTap 注入方法,其实应该差不多的。譬如对于 I/O error 来说:

  1. 系统发起一次 I/O request,进入 SCSI layer。
  2. 进行 scsi_dispatch_cmd,调用到对应的 SCSI command
  3. 使用 SystemTap 注入,将数据的 length 改成 0,并更改 SCSI 的 command。
  4. 将 command 发到 SCSI 的设备执行。
  5. 收到 SCSI 设备的执行结果。
  6. 使用一个 fake 的结果替换,生成一个 SCSI Error。
  7. 调用 scsi_decide_disposition,返回一个 I/O Error。

可以看到,只要我们理解了整个 SCSI 的流程,用 SystemTap 进行注入是非常简单的,具体到作者的代码,原来的已经不能跑了,我找到了一个 Github 的,但也没法运行,于是稍微改了一下,放在我的 fault injection 下面,主要有几个改动:

  1. 原来的 SCSI driver 是在 module 里面,但 CentOS 7 是编译到了 kernel 里面。
  2. 原来 Embedded C 代码使用的是 THIS 来访问参数和返回值,但最新的改成了 STAP_ARG_STAP_RETURN
  3. 原来的 requestbuf_len 没有了,改成了从 request 里面获取 __data_len
  4. 原来 request 的 sector 变量改成了 __sector

但这个只能搞定 I/O error 的,对于 I/O timeout,CentOS 7 的内核已经没有了 SCSI 相关的 timer 函数,所以就没有折腾了。

VFS Fault Injection

上面使用的是 SCSI 的方式,但并没有很好的处理 timeout,于是我想,是不是能够更简单一点,直接在 VFS 或者 syscall 这层上面处理,于是立马开始弄,首先就是 timeout,这个比较难模拟,但可以模拟 delay,于是开干:

probe vfs.read.return
{
    udelay(300)   
}

上面的脚本就是在 read 返回的时候 delay 300 us,模拟 I/O 的延迟,实际测试也发现读取速度慢了下来。

然后就是 I/O error,想到应该也能直接改掉 return 的返回值,于是开干:

probe vfs.write.return
{
    $return = -28
}

上面在 write 返回的时候,将结果改成了 -28,也就是 no space 的错误。

我们还可以做的更多,譬如在 write 的时候,直接将 buf 里面的数据给改掉,或者在 read 的时候也改掉对应的数据。

小结

可以看到,使用 SystemTap 能非常方便的进行 fault injection,这也会成为我后面一个重点比较关注的地方,因为我们不光要给 I/O 注入错误,还可以处理 CPU,Scheduler,Memory 这些。总之,我们就是需要尽量的将系统搞坏,然后看我们整个系统在这些极端情况下会是怎样的反映。

如果有谁对这块感兴趣,喜欢折腾 kernel,喜欢用 SystemTap 来进行动态追踪,错误注入,欢迎联系我:tl@pingcap.com

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,835评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,598评论 1 295
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,569评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,159评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,533评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,710评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,923评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,674评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,421评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,622评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,115评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,428评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,114评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,097评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,875评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,753评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,649评论 2 271

推荐阅读更多精彩内容