При пристальном рассмотрении выяснилось, что ядро всего лишь течет:
$ slabtop
OBJS ACTIVE USE OBJ SIZE SLABS OBJ/SLAB CACHE SIZE NAME
441920 441450 99% 1.00K 13810 32 441920K kmalloc-1024
224070 222908 99% 0.19K 5335 42 42680K kmalloc-192
38304 21198 55% 0.19K 912 42 7296K dentry
25602 25133 98% 0.12K 753 34 3012K kernfs_node_cache
19380 19380 100% 0.04K 190 102 760K Acpi-Namespace
$ uname -a
Linux zdtm.openvz.org 4.10.17-200.fc25.x86_64 #1 SMP Mon May 22 18:12:57 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
“Течёт и течёт, с кем не бывает”, подумали мы и обновились до 4.11. В той части CI у нас стоит Fedora, и тогда это было самое новое её ядро. Загрузили, и уже через пару минут CI нам снова передал привет посредством неработающего netfilter-а — при попытке удалить добавленное правило выдавалась невнятная ошибка:
[root@zdtm ~]# iptables -w -t filter --protocol tcp -A INPUT --dport 12345 -j DROP
[root@zdtm ~]# iptables -w -t filter --protocol tcp -D INPUT --dport 12345 -j DROP
iptables: Bad rule (does a matching rule exist in that chain?).
С помощью iptables CRIU блокирует сеть, чтобы зафиксировать состояние TCP сокетов. Ясно, что с таким багом наш CI работать тоже не мог. Недолго думая, мы собрали и загрузили ядро прямо из дерева Линуса, но и оно проработало недолго — снова потекла память:
[root@zdtm criu]# cat /proc/slabinfo | grep mnt
mnt_cache 36456 36456 384 42 4 : tunables 0 0 0 : slabdata 868 868 0
[root@zdtm criu]# python test/zdtm.py run -t zdtm/static/env00 --iter 10 -f ns
========================= Run zdtm/static/env00 in ns ==========================
Start test
./env00 --pidfile=env00.pid --outfile=env00.out --envname=ENV_00_TEST
Run criu dump
Run criu restore
Run criu dump
....
Run criu restore
Send the 15 signal to 339
Wait for zdtm/static/env00(339) to die for 0.100000
Removing dump/zdtm/static/env00/31
========================= Test zdtm/static/env00 PASS ==========================
[root@zdtm criu]# cat /proc/slabinfo | grep mnt
mnt_cache 36834 36834 384 42 4 : tunables 0 0 0 : slabdata 877 877 0
О проблеме доложили в lkml и пошли дальше заниматься своими делами. Вскоре наш соотечественник Александр Виро ответил, что Андрей Вагин нехороший человек и плохо объяснил предпосылки проблемы. А Александр, на минуточку, является Самым Главным Человеком в подсистеме, отвечающей за все, что связано с файлами, файловыми системами. Он не отличается быстротой реакции на присылаемые изменения, но если вы прислали какое-то г… но, то ответ настигнет вас сразу и неизбежно. А если вы тугодум, то он даже на родном объяснит все простыми словами.
Иногда проще починить баг, чем объяснять, что случилось, чем Андрей и занялся. Через некоторое время патч был готов, он был послан в рассылку и приложен к ядру, которое, в свою очередь, было загружено на CI. С чувством исполненного долга Андрей пошел заниматься своими делами. Виро молчал, что означало отсутствие очевидных проблем в патче. Еще одним признаком избавления от старой проблемы явилось сообщение о новой проблеме.
[ 699.207570] BUG: Bad page state in process ip6tables-save pfn:1499f4
Времени и желания разбираться уже не оставалось, ограничились письмом в lkml, а в CI загрузили ядро 4.10, у которого было существенное преимущество — оно работало и не падало. Да, оно немного текло, и мы решили перезагружать машину раз в сутки. Кто-то вспомнил о старых добрых временах, когда все подряд перегружали винду, если та начинала тормозить.
Свежий баг мировыми усилиями довольно оперативно починили. На CI установили Самое Новое и Лучшее ядро, но не тут-то было. Посыпались ошибки в тестах, примерно в каждом втором.
На этом направлении оборону держал Кирилл Горкунов (отчасти из-за того, что Андрей пошел спать). К утру в lkml развернулась большая дискуссия. Оказалось, что наши коллеги-ядерщики чинили Страшную Уязвимость CVE-2017-1000364 и поломали обратную совместимость пользовательского API. Поломка эта была практически умышленной: без этого код становился намного сложнее, и сообщество, скрепя сердце, решилось на крайние меры. А в силу того, что речь шла о Страшной Уязвимости (нужна картинка windows security model с воротами без забора), изменения не обсуждались публично и были наскоро влиты в ядро. Сразу после этого оказалось, что изменения привнесли в ядро другой баг, который тоже оказался Страшной Уязвимостью, и ещё несколько дней ушло на уже открытые дебаты по новой проблеме.
Возникшая неразбериха сказалась на дистрибутивах. Когда инженеры RedHat и Ubuntu переносили эти изменения в свои ядра, что-то пошло не так, и оба дистрибутива оказались сломанными двумя разными способами. Для нас это тоже было критично, так как часть нашего CI крутится в Travis, а там на выбор предлагается только Ubuntu. Другая часть CI крутится на Fedora, заменить её там на Ubuntu можно ради однородности, но уж конечно не в спешке. Так что в Fedora просто загрузили неродное ядро, его-то должны были уже починить! После установки по привычке сразу посмотрели не течёт ли оно.
unreferenced object 0xffff88006342fa38 (size 1024):
comm "ip", pid 15477, jiffies 4295982857 (age 957.836s)
hex dump (first 32 bytes):
b8 b0 4d a0 ff ff ff ff c0 34 c3 59 00 88 ff ff ..M......4.Y....
04 00 00 00 a4 01 00 00 00 00 00 00 00 00 00 00 ................
backtrace:
[ffffffff8190510a] kmemleak_alloc+0x4a/0xa0
[ffffffff81284130] __kmalloc_track_caller+0x150/0x300
[ffffffff812302d0] kmemdup+0x20/0x50
[ffffffffa04d598a] dccp_init_net+0x8a/0x160 [nf_conntrack]
[ffffffffa04cf9f5] nf_ct_l4proto_pernet_register_one+0x25/0x90
Течёт. Необходимые изменения нашлись быстро, по какой-то причине maintainer DCCP не отправил их Линусу, и они затерялись в его дереве. Берём патч (на доклад в рассылку настроения уже нет), перезагружаемся в новое ядро.
В одном из своих произведений Марк Твен описывает человека по имени Оливер, который отправился на серебряные месторождения. Путешествие проходило в очень тяжёлых условиях, но Оливер молча переносил все выпавшие на его долю тяготы. Однажды, во время длительной стоянки (возможно это был уже конец их похода) в его жилье, проломив крышу, свалился мул. На следующий день ситуация повторилась, и Оливер перенёс свой домик в сторону, где мулы не гуляли, но это его не спасло — в дом, опять сломав крышу, упала корова. В тот момент Оливер впервые выразил своё недовольство происходящим фразой: «Это уже становится однообразным», после чего подал в отставку и уехал.
«Это уже становится однообразным», подумал Андрей, посмотрев на загруженное ядро.
unreferenced object 0xffff9f79442cd980 (size 112):
comm "kworker/1:4", pid 15416, jiffies 4307432421 (age 28687.562s)
hex dump (first 32 bytes):
00 00 00 00 ad 4e ad de ff ff ff ff 00 00 00 00 .....N..........
ff ff ff ff ff ff ff ff b8 39 1b 97 ff ff ff ff .........9......
backtrace:
[ffffffff9591d28a] kmemleak_alloc+0x4a/0xa0
[ffffffff95276198] kmem_cache_alloc_node+0x168/0x2a0
[ffffffff95279f28] __kmem_cache_create+0x2b8/0x5c0
[ffffffff9522ff57] create_cache+0xb7/0x1e0
[ffffffff952305f8] memcg_create_kmem_cache+0x118/0x160
[ffffffff9528eaf0] memcg_kmem_cache_create_func+0x20/0x110
[ffffffff950cd6c5] process_one_work+0x205/0x5d0
[ffffffff950cdade] worker_thread+0x4e/0x3a0
[ffffffff950d5169] kthread+0x109/0x140
[ffffffff9592b8fa] ret_from_fork+0x2a/0x40
[ffffffffffffffff] 0xffffffffffffffff
unreferenced object 0xffff9f798a79f540 (size 32)
К чести Андрея, в отставку он не подал, а доложил о проблеме в lkml, настроил профилактическую перезагрузку, запустил CI и занялся своими делами. Через полдня пришло письмо о новых проблемах.
> [22458.504137] BUG: Dentry ffff9f795a08fe60{i=af565f,n=lo} still in
> use (1) [unmount of proc proc]
> [22458.505117] ------------[ cut here ]------------
> [22458.505299] WARNING: CPU: 0 PID: 15036 at fs/dcache.c:1445
…
> [22458.515141] ---[ end trace b37db95b00f941ab ]---
> [22458.519368] VFS: Busy inodes after unmount of proc. Self-destruct
> in 5 seconds. Have a nice day...
> [22458.813846] BUG: unable to handle kernel NULL pointer dereference
> at 0000000000000018
…
Ядро не просто текло, оно вешало тесты, само зависало в непонятном состоянии, но признаки жизни подавало. Проблема показалась знакомой. Выяснилось, что об этой проблеме Андрей уже писал в lkml несколько месяцев назад, но тогда никому до этого не было дела. В этот раз решили проинформировать гораздо больше людей, и реакция наконец-то возникла. Эрик Бидерман почти сразу нашёл проблемный патч, но суть самой проблемы спустя неделю всё ещё оставалась покрытой мраком.
Сейчас на CI машинах у нас загружено латаное-перелатаное ядро, оно пока не падает, но все еще подтекает. В основной ветке у Линуса все эти проблемы цветут и немного пахнут, но это не помешало выпуску 4.12 ядра.
Люди,
В заключение хочется процитировать Александра Виро, который на ядерном саммите около десяти лет назад сказал: «We're discussing a lot how to encourage people write the kernel code. But I'd like someone to start a discussion about how to encourage people READ this damned thing.»
Авторы: Павел Емельянов, Кирилл Горкунов и Андрей Вагин.
Комментарии (44)
vesper-bot
11.07.2017 09:00Не такая простая вещь — читать ядерный код. Лениво, хотя бы. Вот и не получается у них это поощрять. На баг-баунти у сообщества денег нет, а было бы хорошее поощрение. А если кто проспонсирует, потом будет права предъявлять — вот и имеем, что имеем.
avagin
11.07.2017 09:05+1Надо понимать, что большая часть людей разрабатывает ядро за деньги. На мой взгляд, основная проблема — это практически полное отсутствие тестов. Они потихоньку появляются, но пока это все в очень начальном состоянии. Мы гоняем CRIU тесты на linux-next, и даже они ловят багов в ядре столько, что мы не успеваем их разгребать. Обычно, ждем пару дней и вот если баг не рассасывается, начинаем смотреть.
Nakosika
11.07.2017 11:42+5То чувство когда из-за огромного объема и влажности кода нужно использовать новые методики, а ребята еще старые не начали использовать.
Nakosika
11.07.2017 13:06+4Конечно не влажности а важности, будь проклят свайп. :D
mihail_romanov
11.07.2017 19:45+1Ну почему же, получилось очень даже «слегка сырой» == «влажный» код. :)
avagin
11.07.2017 09:07+5А самое главное, ядерный код очень легко читается и воспринимается. Мне много раз приходилось смотреть разные проекты, и в плане читаемости кода, ядро — это почти идеал. Писать такой код на порядок сложнее, но это уже другой разговор.
xztau
11.07.2017 09:10+3Сколько фамилий… Вы у следователя это писали? Это статья или чистосердечное?
avagin
11.07.2017 09:11+4Да, а чего скрывать то? Вот они все https://github.com/xemul/criu/graphs/contributors
xztau
11.07.2017 09:17+4Я про стиль Вы, кажется, подельников заложили. А за статью спасибо.
avagin
11.07.2017 09:21+3Стиль такой, скорей всего, потому что писали последовательно три человека. Все с третьем лице выглядит, странновато, но так уж получилось. С одной стороны после трех недельного марафона, хотелось выговориться, но с другой стороны уже тошнило:)
kkx
11.07.2017 10:12+1Молодцы! Приятно видеть профессионализм и что команда VZ только крепчает!
P.S. А Linux уже и вправду не торт :(( у нас mm все никак не заработает… начинается сильный swapout на элементарных нагрузках…
acmnu
11.07.2017 10:15+2Я понимаю, что ковыряние в ядре ваша специализация. Вы именно этим зарабатываете, но держать не LTS дистр на инфраструктурном сервере… Зачем?
avagin
11.07.2017 10:23+1Для тестирования CRIU нужно очень свежее ядро. У нас есть даже списочек патчей, которые так или иначе касаются CRIU https://criu.org/Upstream_kernel_commits. Тут можно заметить, что почти в каждом ядре появляется что-то новое, и мы хотим все это покрывать тестами.
acmnu
11.07.2017 10:45Для тестирования CRIU нужно очень свежее ядро.
Ну это же один сервер, ну или немного? Просто из первого обзаца сложилось впечатление, что в CI у вас одна только Fedora.
avagin
12.07.2017 02:04+1CRIU — проект небольшой. Пока нам для тестирования хватает двух серверов (x86_64) и travis-ci. Есть еще виртуалки под другие архитектуры, но там с ядрами мы экспериментов не ставим.
К слову, у нас есть забавный эксперимент над трависом, когда мы там компиляем свое ядро и подменяем им существующее. Сейчас мы это используем для тестирования Linux-next
https://travis-ci.org/avagin/criu/builds/252438980
jamakasi666
11.07.2017 10:32+1Интересно а в bsd ядрах такие же проблемы?
jamakasi666
11.07.2017 11:53+3Вообще сейчас перечитал статью еще раз и понял истину. Всетаки идеи open source работают и тут это наглядно видно. Обнаружен баг, обнаружены причины, дефект устранен(ну почти) и все довольны. В случае тех же ms было бы намного сложнее выявить проблему, еще сложнее достучаться и очень долго ждать когда это пофиксят. Тут же прям здесь и сейчас пусть и без пуша(как я понял) патча в гит ядра.
AdVv
11.07.2017 17:13Вы имеете негативный опыт багрепортов в МС, или вам так просто кажется?
jamakasi666
12.07.2017 08:05+1Пару раз приходилось и опыт крайне негативный.
avagin
12.07.2017 08:22В чем был негатив?
Frankenstine
13.07.2017 16:43Довелось разок, давненько, столкнуться со странным поведением относительно новой виндовс виста. Подключен к ADSL роутеру компьютер с Windows XP и ноутбук с вистой. На компьютере всё работает нормально, а виста упорно твердит, что интернета нет. Обращение в службу поддержки МС привело к предложению к нам сначала получить в письменном виде справку от провайдера, что проблема не у них, и предоставить её в МС. После такой «поддержки» я больше никогда не пытался с ними что-либо решать.
alar0n
11.07.2017 17:13+2Тут в соседней теме кажется проблема с ядром у ms. Посмотрим кто быстрее справится :)
https://habrahabr.ru/post/332816/[perevod]-24-yadernyy-cpu--a-ya-ne-mogu-sd/
Ivan_83
12.07.2017 12:12+1Нет в BSD таких проблем.
У фри есть ветка HEAD — там бывает что то ломается, на ней сидят разработчики которые могут сами всё починить. Те кто не ищет приключений (те кому работу работать, жизнь жить и тп) её не ставит себе, кроме случаев когда в head есть какая то оч нужная фича которая не будет бэкпортирована.
Есть ветки STABLE и RELEASE — туда обычно или бэкпортируется аккуратно. Оно изначально получается из HEAD, в которой отловили большинство багов и стабилизировали.
Описанное в заметке это говнокодинг какой то, у нас во фряшечке я такого не видел.avagin
12.07.2017 18:06+3Так в Linux тоже есть люди, которые такого не видели, это же не говорит, что такого нет. Ну, и здесь мы говорим про аналог вашего HEAD.
apro
11.07.2017 13:46А не хотите перевести и запостить статью на каком-нибудь популярном
англоязычном ресурсе? Автоматические тесты, насколько я знаю, есть у некоторых
подсистем, типа файловых систем, неплохо было бы начать движение к объединению,
интеграции и т.д.avagin
11.07.2017 20:11+1Да, проблема известная. Прямо сейчас вижу здоровый тред, где народ обсуждает тесты для ядра в преддверии кернел самита. Может и переведем, посмотрим как настроение будет.
lleo_aha
12.07.2017 02:57А мне кажется статья написана достаточно нездорово. В духе «вот мы и так и сяк а всё равно ничего не работает». Хотя вроде половина авторов статьи в ней же и участвует. Я вот почитал — думаю opensource действительно работает :) А если автор все таки не согласен — чёж там, слазьте на «стабильную» винду и радуйтесь
avagin
12.07.2017 03:11+2Мне кажется вы меня неправильно поняли. На винде если вы встретите баг, и вы не большая корпорация, вы ничего сделать не сможете. А здесь, мы имея ограниченные ресурсы, смогли победить все проблемы и последнюю неделю наш CI крутится, не течет и не падает. На самом деле вся прелесть opensource именно в этом. Любую ошибку можно исправить за счет собственного времени.
Второй вывод можно сделать в сторону LTS версий. Да, там обычно не самое свежее ядро, но на то есть причины, и эта статья яркий пример этому. Обычно мы не собираем свои ядра и крутимся на том, что пришло от федоры, но иногда случаются вот такие черные полосы. Сразу скажу, это бывает не так часто. А на столько неприятная ситуация возникла впервые за 6 лет.
akden
19.07.2017 08:48-1Господа авторы в качестве бреда, дайте расшифровку CRIU и CI, ну так типа возможно наверное будет логично, скажу вам по секрету не у всех столько времени, как у вас, чтобы гуглить, искать все ваши обозначения, так же хочу напомнить, что это не специфичный сайт по openvz, linux и поэтому было бы неплохо продумать этот вопрос, заранее благодарю,
avagin
19.07.2017 09:28+1Я рекомендую вам пойти научиться хорошим манерам, а потом приходите, я вам все расшифрую.
merrygod
21.07.2017 00:06+1Извините, но хабр это не очередной форум, сайт howto и прочий полезный инструмент для повседневных задач. Статья пишется для людей которые понимают тему или интересуются ей, или заинтересовались. Именно по этому статьи размещаются в определенных хабах и с определенными тегами. Если вы считаете, что ваше время дороже время автора и вам не хватает времени погуглить — проходите мимо.
P.S. Простите, возмутило.
nick_volynkin
Здесь как будто предложение не закончено. Или хотя бы кавычек и точки не хватает.
avagin
Поправил. Спасибо. Рад, что кто-то дочитал статью до конца;)
NLO
НЛО прилетело и опубликовало эту надпись здесь
avagin
И это поправил. Спасибо. Кажется, надо быть более внимательным:).
zag2art
вот и с ядром так же
bjornd
А теперь предложение грамматически неверное. Частицы «to» перед «write» не хватает.