Це викликано потоком життя, коли 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 може бути зачеплена відома проблема, яка змушує сторожового NMI виявити зависання при отриманні повідомлення про випускну секунду. Це питання вирішується своєчасно. Якщо ваші системи отримали оголошення про випускну секунду, і це питання не виникло, тоді вони більше не зачіпаються ".
ОНОВЛЕННЯ: вищевказану мову було видалено зі статті Red Hat; і було додано друге рішення KB, в якому детально описується проблема збою adjtimex (2): https://access.redhat.com/knowledge/solutions/154713
Однак зміна коду у публікації LKML від інженера IBM Джона Стульца зазначає, що також може бути глухий кут, коли застосовано стрибкову секунду, тому ви, можливо, захочете відключити високосну секунду шляхом перезавантаження або використання adjtimex (8) після відключення ntpd.
ЗАКЛЮЧНЕ ОНОВЛЕННЯ:
Ну, я не розробник ядра, але я знову переглянув патч Джона Стульца тут: https://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h = 6b43ae8a619d17c4935c3320d2ef9e92bdeed05d
Якщо я читаю це правильно цього разу, я помилявся з приводу того, що стався ще один глухий кут, коли застосовано високосну секунду. Це, мабуть, також є думкою Red Hat, виходячи з їхньої статті KB. Однак якщо ви відключили ntpd, тримайте його відключеним ще 10 хвилин, щоб ви не потрапили в тупик, коли ntpd викликає adjtimex (2).
Ми дізнаємось, чи скоро з’являться ще помилки :)
ДРУГЕ ОНОВЛЕННЯ ПОСТАВКИ:
Останні кілька годин я провів за читанням ядра ntpd та попереднього виправлення (баггі), і, хоча тут я можу помилятися, я спробую пояснити, що я думаю, що відбувалося:
По-перше, ntpd весь час викликає adjtimex (2). Це робиться як частина його "фільтру тактового циклу", визначеного у local_clock у ntp_loopfilter.c. Ви можете побачити цей код тут: 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" і викликає adjtimex (2) (через його переносимість).
Цей системний виклик пробивається до ядра. Ось відповідний код ядра: https://github.com/mirrors/linux/blob/a078c6d0e6288fad6d83fb6d5edd91ddb7b6ab33/kernel/time/ntp.c
Шлях кодексу ядра приблизно такий:
- рядок 663 - початок програми do_adjtimex.
- рядок 691 - скасувати будь-який існуючий таймер стрибків-секунд.
- рядок 709 - захопити ntp_lock spinlock (цей замок задіяний у можливій аварії лайфлака)
- рядок 724 - виклик process_adjtimex_modes.
- рядок 616 - виклик process_adj_status.
- рядок 590 - встановити глобальну змінну time_status на основі прапорів, встановлених у виклику adjtimex (2)
- рядок 592 - перевірити глобальну змінну time_state. у більшості випадків телефонуйте ntp_start_leap_timer.
- рядок 554 - перевірити глобальну змінну time_status. STA_INS буде встановлено, тому встановіть time_state на TIME_INS та зателефонуйте hrtimer_start (інша функція ядра), щоб запустити другий таймер стрибка. у процесі створення таймера цей код захоплює xtime_lock. якщо це трапиться, поки інший процесор вже схопив xtime_lock та ntp_lock, тоді ядра ядра. саме тому Джон Стульц написав патч, щоб уникнути використання хртимерів. Це те, що завдало сьогодні всім неприємностей.
- рядок 598 - якщо ntp_start_leap_timer насправді не запустив стрибковий таймер, встановіть time_state на TIME_OK
- рядок 751 - якщо припустимо, що ядро не розгортається, стек розкручується і вивільняється спінлок ntp_lock.
Тут є кілька цікавих речей.
По-перше, рядок 691 скасовує існуючий таймер щоразу, коли викликається adjtimex (2). Потім 554 знову створює цей таймер. Це означає, що кожного разу, коли ntpd запускав свій фільтр тактового циклу, викликався код помилки.
Тому я вважаю, що Red Hat помилився, коли вони сказали, що після того, як ntpd встановив прапор високосної секунди, система не вийде з ладу. Я вважаю, що кожна система, яка працює з ntpd, мала потенціал запускати кожні 17 хвилин (або більше) за 24 години до високосної секунди. Я вважаю, що це також може пояснити, чому так багато систем вийшло з ладу; одноразова ймовірність аварії була б набагато рідшою, ніж 3 шанси на годину.
ОНОВЛЕННЯ: У рішенні KB Red Hat за адресою https://access.redhat.com/knowledge/solutions/154713 інженери Red Hat дійшли такого ж висновку (що запуск ntpd буде постійно потрапляти на помилку коду). І справді вони зробили це за кілька годин до того, як я. Це рішення не було пов'язане з основною статтею на веб- сайті 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 та відключити прапор другого стрибка.
І кілька заключних думок:
- жоден з постачальників Linux не помітив патч Джона Стульца і застосував його до своїх ядер :(
- Чому Джон Стульц не попередив деяких постачальників, що це було потрібно? можливо, шанс виникнення лайфлок виглядав досить низьким, тому шум не був обґрунтованим.
- Я чув повідомлення про те, що процеси Java блокуються або крутяться, коли застосовано високосну секунду. Можливо, ми повинні слідувати керівництву Google і переосмислити, як ми застосовуємо високосні секунди до наших систем: http://googleblog.blogspot.com/2011/09/time-technology-and-leaping-seconds.html
06/02 Оновлення від Джона Стульца:
https://lkml.org/lkml/2012/7/1/203
Допис містив покрокове ознайомлення з тим, чому стрибкова секунда призвела до того, що таймери futex закінчуються передчасно та безперервно, спричиняючи завантаження процесора.