3.2 linux-2.6.25到2.6.27内核版本的系统死锁
Bug 479765 - Leap second message can hang the kernel 描述了leap second会对系统产生影响的原因:
当一个leap second被插入或删除时,内核会打印一条相关信息:
[69596.647516] Clock: inserting leap second 23:59:60 UTC
而该信息的打印会因xtime_lock而造成系统死锁。
下面是2.6.26内核下该问题出现时的栈信息(this is with Fedora 8 and
kernel kernel-2.6.26.6-49.fc8.x86_64):
#0 ktime_get_ts (ts=0xffffffff8158bb30) at include/asm/processor.h:691
#1 0xffffffff8104c09a in ktime_get () at kernel/hrtimer.c:59
#2 0xffffffff8102a39a in hrtick_start_fair (rq=0xffff810009013880,
p=<value optimized out>) at kernel/sched.c:1064
#3 0xffffffff8102decc in enqueue_task_fair (rq=0xffff810009013880,
p=0xffff81003fb02d40, wakeup=1) at kernel/sched_fair.c:863
#4 0xffffffff81029a08 in enqueue_task (rq=0xffffffff8158bb30,
p=0xffff81003b8ac418, wakeup=-994836480) at kernel/sched.c:1550
#5 0xffffffff81029a39 in activate_task (rq=0xffff810009013880,
p=0xffff81003b8ac418, wakeup=20045) at kernel/sched.c:1614
#6 0xffffffff8102be38 in try_to_wake_up (p=0xffff81003fb02d40,
state=<value optimized out>, sync=0) at kernel/sched.c:2173
#7 0xffffffff8102be9c in default_wake_function (curr=<value optimized out>,
mode=998949912, sync=20045, key=0x4c4b40000) at kernel/sched.c:4366
#8 0xffffffff810492ed in autoremove_wake_function (wait=0xffffffff8158bb30,
mode=998949912, sync=20045, key=0x4c4b40000) at kernel/wait.c:132
#9 0xffffffff810296a2 in __wake_up_common (q=0xffffffff813d3180, mode=1,
nr_exclusive=1, sync=0, key=0x0) at kernel/sched.c:4387
#10 0xffffffff8102b97b in __wake_up (q=0xffffffff813d3180, mode=1,
nr_exclusive=1, key=0x0) at kernel/sched.c:4406
#11 0xffffffff8103692f in wake_up_klogd () at kernel/printk.c:1005
#12 0xffffffff81036abb in release_console_sem () at kernel/printk.c:1051
#13 0xffffffff81036fd1 in vprintk (fmt=<value optimized out>,
args=<value optimized out>) at kernel/printk.c:789
#14 0xffffffff81037081 in printk (
fmt=0xffffffff8158bb30 "yj$\201????\2008\001\t") at kernel/printk.c:613
#15 0xffffffff8104ec16 in ntp_leap_second (timer=<value optimized out>)
at kernel/time/ntp.c:143
#16 0xffffffff8104b7a6 in run_hrtimer_pending (cpu_base=0xffff81000900f740)
at kernel/hrtimer.c:1204
#17 0xffffffff8104b86a in run_hrtimer_softirq (h=<value optimized out>)
at kernel/hrtimer.c:1355
#18 0xffffffff8103b31f in __do_softirq () at kernel/softirq.c:234
#19 0xffffffff8100d52c in call_softirq () at include/asm/current_64.h:10
#20 0xffffffff8100ed5e in do_softirq () at arch/x86/kernel/irq_64.c:262
#21 0xffffffff8103b280 in irq_exit () at kernel/softirq.c:310
#22 0xffffffff8101b0fe in smp_apic_timer_interrupt (regs=<value optimized out>)
at arch/x86/kernel/apic_64.c:514
#23 0xffffffff8100cf52 in apic_timer_interrupt ()
at include/asm/current_64.h:10
#24 0xffff81003b9d5a90 in ?? ()
#25 0x0000000000000000 in ?? ()
从上面的栈信息我们可以发现:该问题的出现原因在于当对leap second进行操作(插入或删除)之前,已经获取了xtime_lock锁;而之后在调用printk()打印日志信息时,printk()中会尝试唤醒klogd内核线程,在唤醒过程中会调用到公平调度类的相关函数,其中会调用ktime_get()获取时间信息,其中会再次尝试获取xtime_lock锁,从而造成死锁。
该问题部分来源于hrtick_start_fair()函数的引入。是由commit 8f4d37ec (high-res preemption tick)引发,大概在2.6.25引入。所以在2.6.25之前的内核,不会发生这个死锁。
而在2.6.28, 引入了commit b845b517,printk()中的wake_up_klogd()不会直接wake_up klogd()也就不会触发后续的xtime_lock,也就避免了死锁的发生。
所以,该原因引起的系统死锁只可能发生在linux内核2.6.25到2.6.27版本下。
Sles11使用2.6.27内核,属于比较危险的部分内核。但是Novell声称已经引入了commit b845b517b5e3706a3729f6ea83b88ab85f0725b0,因而不存在该问题,而且几个小时的实验后系统仍然正常。
此问题影响的版本还有 RHEL4:kernel-2.6.9.89.EL之前的版本,RHEL5.3:kernel-2.6.18-128.37.1.el5之前的版本。现网centos5.5使用的内核版本是2.6.18-194.el5,其不受影响。
3.3 linux-3.4内核版本的系统活锁
08年的commit:https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=7dffa3c673fbcf835cd7be80bb4aec8ad3f51168中为了解决之前遇到的leap second问题而将对leap second的处理从second_overflow()中独立出来,使用定时器来完成此工作。但是12年的commit:https://lkml.org/lkml/2012/3/15/616
认为该patch存在如下可能的livelock场景:
CPU 0 CPU 1
do_adjtimex()
spin_lock_irq(&ntp_lock);
process_adjtimex_modes(); timer_interrupt()
process_adj_status(); do_timer()
ntp_start_leap_timer(); write_lock(&xtime_lock);
hrtimer_start(); update_wall_time();
hrtimer_reprogram(); ntp_tick_length()
tick_program_event() spin_lock(&ntp_lock);
clockevents_program_event()
ktime_get()
seq = req_seqbegin(xtime_lock);
问题在于,引入ntp_lock的commit:http://patches.linaro.org/5122/是在3.4内核才引入的,且在3.4内核得到了修复,因此此问题对3.4以前和以后的内核无影响。
3.4 linux-2.6.32内核插入闰秒可能出现高CPU消耗
2012年的闰秒插入当时导致了一些互联网公司的服务器高cpu消耗,其问题根源在以下网址得到了阐述:https://lkml.org/lkml/2012/7/1/203。
3.5 总结
总的来说,闰秒的插入对各主要发行版的影响包括:
1) Centos5.5(原生内核),SUSE Linux Enterprise Server 10,Tencent tlinux release 2.0,windows2003,windows2008,基本无影响。
2)Suse11(2.6.27内核)有潜在影响(见3.2),目前实验验证无影响。
3.)Tlinux-suse,Tencent tlinux release 1.2(2.6.32内核)有潜在影响(见3.4),闰秒插入后在特定情况下可能会出现高CPU消耗,可使用3.4节小程序来设置自动解决。
4.)使用ntpdate方式同步时间的服务器基本无影响,使用ntpd方式同步时间的服务器,或者使用了较新的tzdata(2015版本以上)的服务器,才有可能受到闰秒问题影响。
5)对时间精度要求较高的业务,请在闰秒发生后,及时得与时间服务器进行时间校准。
6)使用其他操作系统的业务,可通过运行3.4小节的测试程序,来模拟闰秒的插入对系统的影响。
业务如果希望完全避免闰秒问题带来的影响,可在2015年6月28日24点前先确认NTP服务已同步,然后关闭NTPD服务(闰秒通知和闰秒处理不是同时进行的,闰秒通知先行下发);在2015年7月1日8点后开启NTPD服务。
4.如何避免闰秒
业务如果希望完全避免闰秒问题带来的影响,可在2015年6月30日08点前先确认NTP服务已同步,然后关闭NTPD服务(闰秒通知和闰秒处理不是同时进行的,闰秒通知先行下发);在2015年7月1日8点后开启NTPD服务。 |