Это вызвано живой блокировкой, когда ntpd вызывает adjtimex (2), чтобы сообщить ядру о необходимости добавления дополнительной секунды. Смотрите публикацию lkml http://lkml.indiana.edu/hypermail/linux/kernel/1203.1/04598.html
Red Hat также должна обновить свою статью базы знаний. 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 обновила свою статью базы знаний, чтобы отметить: «Клиенты RHEL 6 могут быть затронуты известной проблемой, которая заставляет NMI Watchdog обнаруживать зависание при получении сообщения о високосной секунде NTP. Эта проблема решается своевременно. Если ваши системы получили объявление високосного и не возникло этой проблемы, то они больше не затрагиваются ".
ОБНОВЛЕНИЕ: вышеупомянутый язык был удален из статьи Red Hat; и было добавлено второе решение в КБ, детализирующее проблему с ошибкой adjtimex (2): https://access.redhat.com/knowledge/solutions/154713
Тем не менее, изменение кода в сообщении LKML IBM Engineer Джона Стулца отмечает, что может также возникнуть тупик, когда фактически применяется високосная секунда, поэтому вы можете захотеть отключить високосную секунду путем перезагрузки или использования adjtimex (8) после отключения ntpd.
ЗАКЛЮЧИТЕЛЬНОЕ ОБНОВЛЕНИЕ:
Ну, я не разработчик ядра, но я снова рассмотрел патч Джона Стульца здесь: https://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h = 6b43ae8a619d17c4935c3320d2ef9e92bdeed05d
Если я правильно читаю на этот раз, я ошибся из-за того, что возникла еще одна тупиковая ситуация, когда применяется високосная секунда. Похоже, это мнение Red Hat, основанное на их записи в КБ. Однако, если вы отключили ntpd, оставьте его отключенным еще на 10 минут, чтобы вы не зашли в тупик, когда ntpd вызывает adjtimex (2).
Мы скоро узнаем, есть ли еще ошибки :)
ПОСТ-ЛИП ВТОРОЕ ОБНОВЛЕНИЕ:
Я провел последние несколько часов, читая код ядра ntpd и pre-patch (глючный), и, хотя я могу ошибаться, я попытаюсь объяснить, что происходит:
Во-первых, 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 (эта блокировка участвует в возможном сбое livelock)
- строка 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, то ядро блокирует работу. Вот почему Джон Стульц написал патч, чтобы избежать использования hrtimers. Это то, что вызывало у всех проблемы сегодня.
- строка 598 - если ntp_start_leap_timer фактически не запускает таймер скачка, установите для time_state значение TIME_OK
- строка 751 - при условии, что ядро не выполняет живую блокировку, стек разматывается и освобождается спин-блокировка ntp_lock.
Здесь есть пара интересных вещей.
Во-первых, строка 691 отменяет существующий таймер при каждом вызове adjtimex (2). Затем 554 воссоздает этот таймер. Это означает, что каждый раз, когда ntpd запускал свой фильтр циклов синхронизации, вызывался ошибочный код.
Поэтому я считаю, что Red Hat ошиблась, когда они сказали, что как только ntpd установит флаг високосной секунды, система не будет аварийно завершать работу. Я полагаю, что каждая система, на которой запущен ntpd, могла блокироваться в режиме реального времени каждые 17 минут (или более) в течение 24-часового периода перед високосной секундой. Я считаю, что это также может объяснить, почему так много систем вышло из строя; вероятность единовременного сбоя будет гораздо меньше, чем 3 случая в час.
ОБНОВЛЕНИЕ: В решении Red Hat KB на 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, скачкообразно нагружая процессор.