通过core文件可以看到内核崩溃时的堆栈信息,对进一步查找bug很有帮助。可是这时我犯了一个错误,还是在想通过打印日志的方式来定位出BUG原因。跟随着这个错误的想法,依然没有任何头绪。最终我开始把注意力放在堆栈信息上,因为我发现每次阻塞的进程都是应用层的进程(内核模块和应用层有交互),并且调用的流程都是从sys_close()系统调用开始的。而调用堆栈的后半部分,则是处理时钟中断的部分,处理时候中断的时候,还调用到了我的定时器处理函数。堆栈信息如下所示:
Kernel panic - not syncing: softlockup: hung tasks Pid: 2826, comm: fastcache Not tainted 2.6.32-279.el6.x86_64 #1 Call Trace: <IRQ> [<ffffffff814fd11a>] ? panic+0xa0/0x168 [<ffffffff810dadb0>] ? watchdog_timer_fn+0x0/0x1d0 [<ffffffff810daf6d>] ? watchdog_timer_fn+0x1bd/0x1d0 [<ffffffff8109684e>] ? __run_hrtimer+0x8e/0x1a0 [<ffffffff81012bd9>] ? read_tsc+0x9/0x20 [<ffffffff81096bf6>] ? hrtimer_interrupt+0xe6/0x250 [<ffffffffa0259780>] ? fcluster_timer_process+0x0/0x1b0 [fcluster] [<ffffffff81505bdb>] ? smp_apic_timer_interrupt+0x6b/0x9b [<ffffffff8100bc13>] ? apic_timer_interrupt+0x13/0x20 [<ffffffff8127e4ef>] ? __write_lock_failed+0xf/0x20 [<ffffffff81500147>] ? _write_lock+0x17/0x20 [<ffffffffa02597d5>] ? fcluster_timer_process+0x55/0x1b0 [fcluster] [<ffffffff8107e897>] ? run_timer_softirq+0x197/0x340 [<ffffffff810a21c0>] ? tick_sched_timer+0x0/0xc0 [<ffffffff8102b40d>] ? lapic_next_event+0x1d/0x30 [<ffffffff81073ec1>] ? __do_softirq+0xc1/0x1e0 [<ffffffff81096c50>] ? hrtimer_interrupt+0x140/0x250 [<ffffffff8100c24c>] ? call_softirq+0x1c/0x30 [<ffffffff8100de85>] ? do_softirq+0x65/0xa0 [<ffffffff81073ca5>] ? irq_exit+0x85/0x90 [<ffffffff81505be0>] ? smp_apic_timer_interrupt+0x70/0x9b [<ffffffff8100bc13>] ? apic_timer_interrupt+0x13/0x20 <EOI> [<ffffffff814fffcd>] ? _read_lock+0xd/0x20 [<ffffffffa0258ca1>] ? fcluster_conn_out_get+0x51/0xe0 [fcluster] [<ffffffffa02577cd>] ? fcluster_out+0x9d/0x130 [fcluster] [<ffffffff815002fb>] ? _spin_unlock_bh+0x1b/0x20 [<ffffffff8142b45e>] ? release_sock+0xce/0xe0 [<ffffffff814665e9>] ? nf_iterate+0x69/0xb0 [<ffffffff81476fb0>] ? ip_finish_output+0x0/0x310 [<ffffffff814667a4>] ? nf_hook_slow+0x74/0x110 [<ffffffff81476fb0>] ? ip_finish_output+0x0/0x310 [<ffffffff81477364>] ? ip_output+0xa4/0xc0 [<ffffffff81476675>] ? ip_local_out+0x25/0x30 [<ffffffff81476b50>] ? ip_queue_xmit+0x190/0x420 [<ffffffff810724c7>] ? current_fs_time+0x27/0x30 [<ffffffff814281c3>] ? sock_recvmsg+0x133/0x160 [<ffffffff81194ea2>] ? file_update_time+0x62/0x170 [<ffffffff8148b89e>] ? tcp_transmit_skb+0x3fe/0x7b0 [<ffffffff8148dc5b>] ? tcp_write_xmit+0x1fb/0xa20 [<ffffffff811637fb>] ? __kmalloc_node+0x7b/0x100 [<ffffffff8142480a>] ? sock_poll+0x1a/0x20 [<ffffffff8148e610>] ? __tcp_push_pending_frames+0x30/0xe0 [<ffffffff8148e732>] ? tcp_send_fin+0x72/0x1d0 [<ffffffff8147fc26>] ? tcp_close+0x356/0x460 [<ffffffff814a2d47>] ? inet_release+0x67/0x90 [<ffffffff81427169>] ? sock_release+0x29/0x90 [<ffffffff814271e7>] ? sock_close+0x17/0x30 [<ffffffff8117c935>] ? __fput+0xf5/0x210 [<ffffffff8117ca75>] ? fput+0x25/0x30 [<ffffffff8117849d>] ? filp_close+0x5d/0x90 [<ffffffff81178575>] ? sys_close+0xa5/0x100 [<ffffffff8100b0f2>] ? system_call_fastpath+0x16/0x1b这个堆栈信息要从下往上看,也就是说引发这一系列操作是从system_call_fastpath()开始的,时钟中断的处理时从apic_timer_interrupt()函数开始的。每行后面以[fcluster]结束的行对应的函数是我的内核模块中的函数。通过这个堆栈信息可以看到,在_read_lock()函数(这个函数在fcluster_conn_out_get()中间接调用到)执行时发生了时钟中断,进而开始进行软中断的处理,调用到了定时器处理函数fcluster_timer_process()。在fcluster_timer_process()中会有获取写锁的操作,这个操作的时间过长引发了softlockup机制的处理。CentOS6.3的279内核中处理的函数是watchdog_timer_fn(),在这个函数中最终引发了panic操作。