Điều này được gây ra bởi một livelock khi ntpd gọi adjtimex (2) để báo cho kernel chèn một bước nhảy vọt thứ hai. Xem lkml đăng http://lkml.indiana.edu/hypermail/linux/kernel/1203.1/04598.html
Red Hat cũng nên cập nhật bài viết KB của họ. https://access.redhat.com/ledgeledge/articles/15145
CẬP NHẬT: Red Hat có một bài viết KB thứ hai chỉ dành cho vấn đề này tại đây: https://access.redhat.com/ledgeledge/solutions/154713 - bài viết trước dành cho một vấn đề không liên quan trước đó
Cách giải quyết là tắt ntpd. Nếu ntpd đã ban hành lệnh gọi adjtimex (2), bạn có thể cần phải tắt ntpd và khởi động lại để an toàn 100%.
Điều này ảnh hưởng đến RHEL 6 và các bản phát hành khác chạy hạt nhân mới hơn (mới hơn khoảng 2,6,26), nhưng không ảnh hưởng đến RHEL 5.
Lý do điều này xảy ra trước khi bước nhảy vọt thứ hai thực sự được lên kế hoạch là vì ntpd cho phép hạt nhân xử lý bước nhảy vọt thứ hai vào lúc nửa đêm, nhưng cần cảnh báo hạt nhân để chèn bước nhảy vọt thứ hai trước nửa đêm. Do đó, ntpd gọi adjtimex (2) đôi khi trong ngày của bước nhảy vọt thứ hai, tại thời điểm này, lỗi này được kích hoạt.
Nếu bạn đã cài đặt adjtimex (8), bạn có thể sử dụng tập lệnh này để xác định xem cờ 16 có được đặt không. Cờ 16 là "chèn bước nhảy vọt thứ hai":
adjtimex -p | perl -p -e 'undef $_, next unless m/status: (\d+)/; (16 & $1) && print "leap second flag is set:\n"'
CẬP NHẬT:
Red Hat đã cập nhật bài viết KB của họ để lưu ý: "Khách hàng của RHEL 6 có thể bị ảnh hưởng bởi một sự cố đã biết khiến NMI Watchdog phát hiện bị treo khi nhận được thông báo nhảy vọt NTP. Vấn đề này được giải quyết kịp thời. Nếu hệ thống của bạn nhận được thông báo bước nhảy vọt và không gặp phải vấn đề này, sau đó họ không còn bị ảnh hưởng nữa. "
CẬP NHẬT: Ngôn ngữ trên đã bị xóa khỏi bài viết Red Hat; và một giải pháp KB thứ hai đã được thêm vào chi tiết về sự cố sự cố của adjtimex (2): https://access.redhat.com/ledgeledge/solutions/154713
Tuy nhiên, thay đổi mã trong bài viết LKML của Kỹ sư IBM John Stultz lưu ý rằng cũng có thể có sự bế tắc khi bước nhảy vọt thứ hai thực sự được áp dụng, do đó bạn có thể muốn vô hiệu hóa bước nhảy vọt thứ hai bằng cách khởi động lại hoặc sử dụng adjtimex (8) sau khi vô hiệu hóa ntpd.
CẬP NHẬT CUỐI CÙNG:
Chà, tôi không phải là nhà phát triển kernel, nhưng tôi đã xem lại bản vá của John Stultz tại đây: https://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h = 6b43ae8a619d17c4935c3320d2ef9e92bdeed05d
Nếu tôi đọc nó đúng lúc này, tôi đã sai về việc có một bế tắc khác khi bước nhảy vọt thứ hai được áp dụng. Đó dường như cũng là ý kiến của Red Hat, dựa trên mục nhập KB của họ. Tuy nhiên, nếu bạn đã tắt ntpd, hãy tắt nó thêm 10 phút nữa để bạn không gặp bế tắc khi ntpd gọi adjtimex (2).
Chúng tôi sẽ tìm ra nếu có thêm bất kỳ lỗi nào sớm :)
CẬP NHẬT THỨ HAI SAU:
Tôi đã dành vài giờ qua để đọc mã hạt nhân ntpd và tiền vá lỗi (lỗi) và trong khi tôi có thể rất sai ở đây, tôi sẽ cố gắng giải thích những gì tôi nghĩ đang xảy ra:
Đầu tiên, ntpd gọi adjtimex (2) mọi lúc. Nó thực hiện điều này như là một phần của "bộ lọc vòng lặp đồng hồ", được định nghĩa trong local_clock trong ntp_loopfilter.c. Bạn có thể xem mã đó tại đây: http://www.opensource.apple.com/source/ntp/ntp-70/ntpd/ntp_loopfilter.c (từ phiên bản ntp 4.2.6).
Bộ lọc vòng lặp đồng hồ chạy khá thường xuyên - nó chạy mỗi lần ntpd thăm dò các máy chủ ngược dòng của nó, theo mặc định là cứ sau 17 phút trở lên. Bit có liên quan của bộ lọc vòng lặp đồng hồ là:
if (sys_leap == LEAP_ADDSECOND)
ntv.status |= STA_INS;
Và sau đó:
ntp_adjtime(&ntv)
Nói cách khác, vào những ngày có bước nhảy vọt thứ hai, ntpd sẽ đặt cờ "STA_INS" và gọi adjtimex (2) (thông qua trình bao bọc tính di động của nó).
Cuộc gọi hệ thống đó thực hiện theo cách của nó đến kernel. Đây là mã hạt nhân có liên quan: https://github.com/mirrors/linux/blob/a078c6d0e6288fad6d83fb6d5edd91ddb7b6ab33/kernel/time/ntp.c
Codepath hạt nhân đại khái là thế này:
- dòng 663 - bắt đầu thói quen do_adjtimex.
- dòng 691 - hủy bỏ bất kỳ bộ đếm thời gian nhảy vọt thứ hai hiện có.
- dòng 709 - lấy spinlock ntp_lock (khóa này có liên quan đến sự cố livelock có thể xảy ra)
- dòng 724 - gọi process_adjtimex_modes.
- dòng 616 - gọi process_adj_status.
- dòng 590 - đặt biến toàn cục time_status, dựa trên các cờ được đặt trong lệnh gọi của adjtimex (2)
- dòng 592 - kiểm tra biến toàn cục time_state. trong hầu hết các trường hợp, hãy gọi ntp_start_leap_timer.
- dòng 554 - kiểm tra biến toàn cục time_status. STA_INS sẽ được đặt, vì vậy hãy đặt time_state thành TIME_INS và gọi hrtimer_start (một hàm nhân khác) để bắt đầu bộ đếm thời gian nhảy vọt thứ hai. trong quá trình tạo bộ đếm thời gian, mã này lấy xtime_lock. nếu điều này xảy ra trong khi một CPU khác đã lấy xtime_lock và ntp_lock, thì kernel sẽ hoạt động. đây là lý do tại sao John Stultz đã viết bản vá để tránh sử dụng hrtimers. Đây là những gì đã gây ra tất cả mọi người rắc rối ngày hôm nay.
- dòng 598 - nếu ntp_start_leap_timer không thực sự bắt đầu bộ đếm thời gian nhảy vọt, hãy đặt time_state thành TIME_OK
- dòng 751 - giả sử hạt nhân không hoạt động, ngăn xếp không được mở và spinlock ntp_lock được giải phóng.
Có một vài điều thú vị ở đây.
Đầu tiên, dòng 691 hủy bộ đếm thời gian hiện tại mỗi lần điều chỉnh (2) được gọi. Sau đó, 554 tạo lại bộ đếm thời gian đó. Điều này có nghĩa là mỗi lần ntpd chạy bộ lọc vòng lặp đồng hồ, mã lỗi được gọi.
Do đó, tôi tin rằng Red Hat đã sai khi họ nói rằng một khi ntpd đã đặt cờ bước nhảy vọt thứ hai, hệ thống sẽ không gặp sự cố. Tôi tin rằng mỗi hệ thống chạy ntpd có khả năng sinh động cứ sau 17 phút (hoặc hơn) trong khoảng thời gian 24 giờ trước khi bước nhảy vọt thứ hai. Tôi tin rằng điều này cũng có thể giải thích tại sao rất nhiều hệ thống bị sập; cơ hội một lần bị rơi sẽ ít có khả năng bị tấn công hơn so với 3 cơ hội một giờ.
CẬP NHẬT: Trong giải pháp KB của Red Hat tại https://access.redhat.com/ledgeledge/solutions/154713 , các kỹ sư của Red Hat đã đi đến kết luận tương tự (việc chạy ntpd sẽ liên tục gặp mã lỗi). Và thực sự họ đã làm như vậy vài giờ trước khi tôi làm. Giải pháp này không được liên kết đến bài viết chính tại https://access.redhat.com/ledgeledge/articles/15145 , vì vậy tôi đã không nhận thấy nó cho đến bây giờ.
Thứ hai, điều này giải thích tại sao các hệ thống được tải có nhiều khả năng bị sập. Các hệ thống được tải sẽ xử lý nhiều ngắt hơn, khiến hàm kernel "do_tick" được gọi thường xuyên hơn, tạo cơ hội nhiều hơn cho mã này để chạy và lấy ntp_lock trong khi bộ định thời được tạo.
Thứ ba, có khả năng hệ thống bị sập khi bước nhảy vọt thứ hai thực sự xảy ra không? Tôi không biết chắc chắn, nhưng có thể là có, bởi vì bộ đếm thời gian kích hoạt và thực sự thực hiện điều chỉnh bước nhảy vọt thứ hai (ntp_leap_second, trên dòng 388) cũng lấy spinlock ntp_lock và có lệnh gọi đến hrtimer_add_recires_ns. Tôi không biết liệu cuộc gọi đó cũng có thể gây ra tiếng vang hay không, nhưng dường như không thể.
Cuối cùng, điều gì khiến cờ nhuận thứ hai bị vô hiệu hóa sau khi bước nhảy vọt thứ hai chạy? Câu trả lời là ntpd dừng đặt cờ bước nhảy vọt vào một thời điểm nào đó sau nửa đêm khi nó gọi adjtimex (2). Vì cờ không được đặt, kiểm tra trên dòng 554 sẽ không đúng và sẽ không có bộ đếm thời gian nào được tạo và dòng 598 sẽ đặt lại biến toàn cục time_state thành TIME_OK. Điều này giải thích tại sao nếu bạn kiểm tra cờ bằng adjtimex (8) ngay sau bước nhảy thứ hai, bạn vẫn sẽ thấy cờ bước thứ hai được thiết lập.
Nói tóm lại, lời khuyên tốt nhất cho ngày hôm nay dường như là lời khuyên đầu tiên tôi đưa ra: vô hiệu hóa ntpd và vô hiệu hóa cờ nhuận thứ hai.
Và một số suy nghĩ cuối cùng:
- không ai trong số các nhà cung cấp Linux nhận thấy bản vá của John Stultz và áp dụng nó cho hạt nhân của họ :(
- Tại sao John Stultz không cảnh báo một số nhà cung cấp điều này là cần thiết? có lẽ cơ hội của con ruồi dường như đủ thấp để gây ra tiếng ồn.
- Tôi đã nghe các báo cáo về các quy trình Java bị khóa hoặc quay khi bước nhảy vọt thứ hai được áp dụng. Có lẽ chúng ta nên theo dõi sự dẫn dắt của Google và suy nghĩ lại về cách chúng ta áp dụng bước nhảy vọt cho các hệ thống của mình: http://googleblog.blogspot.com/2011/09/time-t Technology -and-leaping- seconds.html
06/02 Cập nhật từ John Stultz:
https://lkml.org/lkml/2012/7/1/203
Bài đăng chứa từng bước từng bước về lý do tại sao bước nhảy vọt thứ hai khiến bộ định thời Futex hết hạn sớm và liên tục, làm tăng tải CPU.