最近客户的centos频繁重启,但是由于没有vmcore文件产生,但客户急于解决,无法等待vmcore,所以只能尝试从堆栈角度分析内核,找出问题的根由。
问题发生在k8s的环境,由于没有开启锁触发kdump功能,所以内核不断报NMI锁住。
由于没有vmcore文件,只能抱着死马当活马医的心态,根据Call Trace流量代码,看是否有发现。从堆栈可以知道,CPU一直在尝试获取一个_raw_write_lock_bh.
_raw_write_lock_bh这是一个写者获取读写锁,并禁止本地软中断。那么说明其他地方已经获取了这个锁,但是一直没释放。从堆栈上的xfrm_policy_flush+0x3a,我们反汇编一下xfrm_policy_flush函数.
由于我们没有vmcore。我们无法获取为何锁.xfrm_policy_lock.无法获取。从代码来分析一下获取锁的条件。
可以得到,如果所的lock->write的值为WRITE_LOCKER_CMP,那么这个时候锁是空闲的,可以获取。
由于缺乏vmcore,我们这个时候无法获取当前lock的信息。我们再往堆栈的前一个函数继续分析。反汇编xfrm_net_init
从内核代码可以知道,发生问题的时候,由于xfrm函数初始化失败,造成了调用xfrm_policy_fini去尝试获取锁。
我们查看整个函数的逻辑发现,锁的初始化竟然在获取锁后面,如果锁没初始化,默认net最大可能就是被初始化为0,那么lock->write的值就不可能为WRITE_LOCKER_CMP,那么这个时候xfrm_finish_ini是比如无法获取到锁,会一直自旋住,直到触发了NMI。
解决方法:
从以上的分析,锁的初始化,使用比如存在问题,应该是先初始化再使用。查看当前centos最新版本,发现该函数的没做任何修改,查看上游社区发现
这个跟我们以前的分析刚好匹配,查看这个修复的对应的patch。https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=c282222a45cb9503cbfbebfdb60491f06ae84b49
从patch的的描述信息,也符合我们的分析过程。到此我们基本能判断了这个问题的根因。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。