이것은 ntpd가 adjtimex (2)를 호출하여 커널에 윤초를 삽입하도록 지시 할 때 라이브 록에 의해 발생합니다. lkml 게시 http://lkml.indiana.edu/hypermail/linux/kernel/1203.1/04598.html 참조
Red Hat은 KB 기사도 업데이트해야합니다. https://access.redhat.com/knowledge/articles/15145
업데이트 : Red Hat은 여기에 단지이 문제에 대한 두 번째 KB 문서를 가지고 : https://access.redhat.com/knowledge/solutions/154713 - 이전 문서 이전, 관련이없는 문제입니다
해결 방법은 ntpd를 끄는 것입니다. ntpd가 이미 adjtimex (2) 호출을 발행 한 경우, ntpd를 비활성화하고 100 % 안전하도록 재부팅해야합니다.
이는 RHEL 6 및 최신 커널을 실행하는 다른 배포판 (약 2.6.26 이상)에는 영향을 주지만 RHEL 5에는 영향을 미치지 않습니다.
실제로 윤초 가 발생 하기 전에 이러한 상황이 발생하는 이유는 ntpd가 커널이 자정에 윤초를 처리하도록 허용하지만 자정 전에 윤초를 삽입하도록 커널에 경고해야하기 때문입니다. 따라서 ntpd는 윤초의 하루 동안 adjtimex (2)를 호출하며이 시점에서이 버그가 발생합니다.
adjtimex (8)가 설치되어 있으면이 스크립트를 사용하여 플래그 16이 설정되어 있는지 확인할 수 있습니다. 플래그 16은 "윤곽 삽입"입니다.
adjtimex -p | perl -p -e 'undef $_, next unless m/status: (\d+)/; (16 & $1) && print "leap second flag is set:\n"'
최신 정보:
Red Hat은 KB 기사를 다음과 같이 업데이트했습니다. "RHEL 6 고객은 NTP leapsecond 알림을 수신 할 때 NMI Watchdog이 정지를 감지하는 알려진 문제의 영향을받을 수 있습니다.이 문제는 적시에 해결됩니다. 윤초 발표에이 문제가 발생하지 않으면 더 이상 영향을받지 않습니다. "
업데이트 : 위의 언어는 Red Hat 기사에서 제거되었습니다. adjtimex (2) 충돌 문제를 자세히 설명하는 두 번째 KB 솔루션이 추가되었습니다. https://access.redhat.com/knowledge/solutions/154713
그러나 IBM 엔지니어 John Stultz가 LKML 게시물의 코드를 변경하면 윤초가 실제로 적용될 때 교착 상태가 발생할 수 있으므로 ntpd를 비활성화 한 후 adjtimex (8)를 재부팅하거나 사용하여 윤초를 비활성화 할 수 있습니다.
최종 업데이트 :
글쎄, 나는 커널 개발자는 아니지만 John Stultz의 패치를 다시 검토했다 : https://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h = 6b43ae8a619d17c4935c3320d2ef9e92bdeed05d
이번에 올바르게 읽으면 윤초가 적용될 때 또 다른 교착 상태가 발생하는 것이 잘못되었습니다. KB 항목을 기반으로 한 Red Hat의 의견이기도합니다. 그러나 ntpd를 비활성화 한 경우 ntpd가 adjtimex (2)를 호출 할 때 교착 상태에 빠지지 않도록 10 분 동안 비활성화하십시오.
우리는 곧 더 이상 버그가 있는지 알아낼 것입니다 :)
도약 후 두 번째 업데이트 :
나는 지난 몇 시간 동안 ntpd 및 pre-patch (버기) 커널 코드를 읽었으며 여기에서 매우 잘못되었을 수도 있지만, 내가 생각하고있는 것을 설명하려고 노력할 것입니다.
먼저, ntpd는 항상 adjtimex (2)를 호출합니다. ntp_loopfilter.c의 local_clock에 정의 된 "클럭 루프 필터"의 일부로이를 수행합니다. http://www.opensource.apple.com/source/ntp/ntp-70/ntpd/ntp_loopfilter.c(ntp 버전 4.2.6부터)에서 해당 코드를 확인할 수 있습니다 .
클럭 루프 필터는 상당히 자주 실행됩니다. ntpd가 업스트림 서버를 폴링 할 때마다 실행되며 기본적으로 17 분 이상입니다. 클럭 루프 필터의 관련 비트는 다음과 같습니다.
if (sys_leap == LEAP_ADDSECOND)
ntv.status |= STA_INS;
그리고:
ntp_adjtime(&ntv)
다시 말해, 윤초가있는 날에 ntpd는 "STA_INS"플래그를 설정하고 aporttime-wrapper를 통해 adjtimex (2)를 호출합니다.
그 시스템 호출은 커널로 향합니다. 관련 커널 코드는 다음과 같습니다. https://github.com/mirrors/linux/blob/a078c6d0e6288fad6d83fb6d5edd91ddb7b6ab33/kernel/time/ntp.c
커널 코드 경로는 대략 다음과 같습니다.
- 663 행-do_adjtimex 루틴 시작.
- 691 행-기존 윤초 타이머를 취소합니다.
- 709 번째 줄-ntp_lock spinlock을 잡아라 (이 자물쇠는 가능한 livelock 충돌과 관련이있다)
- 724 행-process_adjtimex_modes를 호출하십시오.
- 616 행-process_adj_status를 호출하십시오.
- 줄 590-adjtimex (2) 호출에서 설정된 플래그를 기반으로 time_status 전역 변수 설정
- 592 행-time_state 글로벌 변수를 확인하십시오. 대부분의 경우 ntp_start_leap_timer를 호출하십시오.
- 554 행-time_status 전역 변수를 확인하십시오. STA_INS가 설정되므로 time_state를 TIME_INS로 설정하고 hrtimer_start (다른 커널 함수)를 호출하여 윤초 타이머를 시작하십시오. 타이머를 만드는 과정에서이 코드는 xtime_lock을 가져옵니다. 다른 CPU가 이미 xtime_lock 과 ntp_lock을 잡고있는 동안 이런 일이 발생 하면 커널 라이브 록이됩니다. John Stultz가 시간제 사용을 피하기 위해 패치를 작성한 이유입니다. 이것이 오늘날 모든 사람에게 문제를 일으키는 원인입니다.
- 598 행-ntp_start_leap_timer가 실제로 도약 타이머를 시작하지 않은 경우 time_state를 TIME_OK로 설정하십시오.
- line 751-커널이 라이브 록하지 않는다고 가정하면 스택이 풀리고 ntp_lock spinlock이 해제됩니다.
여기 몇 가지 흥미로운 것들이 있습니다.
먼저, 라인 691은 adjtimex (2)가 호출 될 때마다 기존 타이머를 취소합니다. 그런 다음 554는 해당 타이머를 다시 만듭니다. 이것은 ntpd가 클럭 루프 필터를 실행할 때마다 버그가있는 코드가 호출되었음을 의미합니다.
따라서 ntpd가 윤초 플래그를 설정하면 시스템이 중단되지 않는다고 말했을 때 Red Hat이 잘못되었다고 생각합니다. ntpd를 실행하는 각 시스템은 윤초 전 24 시간 동안 17 분 (또는 그 이상)마다 라이브 록이 생길 가능성이 있다고 생각합니다. 나는 이것이 왜 그렇게 많은 시스템이 충돌했는지 설명 할 수 있다고 믿는다. 한 번의 충돌 가능성은 시간당 3 번의 기회에 비해 적을 확률이 훨씬 낮습니다.
업데이트 : https://access.redhat.com/knowledge/solutions/154713 의 Red Hat의 KB 솔루션에서 Red Hat 엔지니어는 동일한 결론에 도달했습니다 (nttpd를 실행하면 버그가있는 코드가 계속 발생합니다). 그리고 실제로 그들은 몇 시간 전에 그렇게했습니다. 이 솔루션은 https://access.redhat.com/knowledge/articles/15145 의 주요 기사에 연결되지 않았으므로 지금까지는 알지 못했습니다.
둘째,로드 된 시스템이 중단 될 가능성이 높은 이유를 설명합니다. 로드 된 시스템은 더 많은 인터럽트를 처리하여 "do_tick"커널 함수가 더 자주 호출되게하여 타이머가 생성되는 동안이 코드가 ntp_lock을 실행하고 포착 할 수있는 기회를 제공합니다.
셋째, 윤초가 실제로 발생할 때 시스템이 충돌 할 가능성이 있습니까? 확실하지는 않지만 아마도 가능합니다. 실제로 타이머가 실행되고 실제로 윤초 조정을 실행하는 타이머 (ntp_leap_second, 388 줄)도 ntp_lock 스핀 락을 잡고 hrtimer_add_expires_ns를 호출합니다. 전화가 라이브 락을 유발할 수 있는지는 모르겠지만 불가능하지는 않습니다.
마지막으로 윤초가 실행 된 후 윤초 플래그가 비활성화되는 원인은 무엇입니까? 대답은 ntpd가 adjtimex (2)를 호출 할 때 자정 이후 어느 시점에서 윤초 플래그 설정을 중지합니다. 플래그가 설정되지 않았으므로 554 행의 검사는 참이 아니며 타이머가 작성되지 않으며 598 행은 time_state 전역 변수를 TIME_OK로 재설정합니다. 이것은 윤초 직후 adjtimex (8)로 플래그를 확인한 경우에도 윤초 플래그 설정이 계속 표시되는 이유를 설명합니다.
요컨대, 오늘 가장 좋은 조언은 내가 처음으로 준 것 같습니다 : ntpd를 비활성화하고 윤초 플래그를 비활성화하십시오.
그리고 마지막 생각들 :
John Stultz의 06/02 업데이트 :
https://lkml.org/lkml/2012/7/1/203
포스트에는 왜 윤초가 futex 타이머가 조기에 지속적으로 만료되어 CPU 부하가 급증하는지에 대한 단계별 안내가 포함되어 있습니다.