11 июля в 07:17

Linux все еще не торт

Эта история началась около месяца назад, когда Кирилл Тхай добавил поддержку вложенных пространств имен в CRIU, после чего наша система CI приказала долго жить. В тот момент ничто не предвещало тех увлекательных приключений, в которые мы оказались вовлечены.

image

При пристальном рассмотрении выяснилось, что ядро всего лишь течет:

$ 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 ядра.

Люди, храните деньги в сберегательных кассах работайте только на стабильных ядрах, если конечно, они у вас есть. Обычному Linux ядру сильно не хватает тестирования.

В заключение хочется процитировать Александра Виро, который на ядерном саммите около десяти лет назад сказал: «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.»

Авторы: Павел Емельянов, Кирилл Горкунов и Андрей Вагин.
Автор: @avagin
Virtuozzo
рейтинг 129,65
Разработчик ПО для контейнерной виртуализации
Похожие публикации

Комментарии (43)

  • 0
    about how to encourage people

    Здесь как будто предложение не закончено. Или хотя бы кавычек и точки не хватает.

    • 0
      Поправил. Спасибо. Рад, что кто-то дочитал статью до конца;)
      • НЛО прилетело и опубликовало эту надпись здесь
        • +2
          И это поправил. Спасибо. Кажется, надо быть более внимательным:).
          • +28
            вот и с ядром так же
          • 0
            We're discussing a lot how to encourage people write the kernel code

            А теперь предложение грамматически неверное. Частицы «to» перед «write» не хватает.
  • 0

    Не такая простая вещь — читать ядерный код. Лениво, хотя бы. Вот и не получается у них это поощрять. На баг-баунти у сообщества денег нет, а было бы хорошее поощрение. А если кто проспонсирует, потом будет права предъявлять — вот и имеем, что имеем.

    • +1
      Надо понимать, что большая часть людей разрабатывает ядро за деньги. На мой взгляд, основная проблема — это практически полное отсутствие тестов. Они потихоньку появляются, но пока это все в очень начальном состоянии. Мы гоняем CRIU тесты на linux-next, и даже они ловят багов в ядре столько, что мы не успеваем их разгребать. Обычно, ждем пару дней и вот если баг не рассасывается, начинаем смотреть.
      • +5

        То чувство когда из-за огромного объема и влажности кода нужно использовать новые методики, а ребята еще старые не начали использовать.

        • +4
          Конечно не влажности а важности, будь проклят свайп. :D
          • +18
            Да нормально получилось. Намёк на сырость кода.
          • +1
            Ну почему же, получилось очень даже «слегка сырой» == «влажный» код. :)
    • +5
      А самое главное, ядерный код очень легко читается и воспринимается. Мне много раз приходилось смотреть разные проекты, и в плане читаемости кода, ядро — это почти идеал. Писать такой код на порядок сложнее, но это уже другой разговор.
  • +3
    Сколько фамилий… Вы у следователя это писали? Это статья или чистосердечное?
    • +4
      Да, а чего скрывать то? Вот они все https://github.com/xemul/criu/graphs/contributors
      • +4
        Я про стиль Вы, кажется, подельников заложили. А за статью спасибо.
        • +3
          Стиль такой, скорей всего, потому что писали последовательно три человека. Все с третьем лице выглядит, странновато, но так уж получилось. С одной стороны после трех недельного марафона, хотелось выговориться, но с другой стороны уже тошнило:)
  • +6

    Спасибо за статью, прикольно знать страшные истории про ядро Linux)

  • +1
    Молодцы! Приятно видеть профессионализм и что команда VZ только крепчает!
    P.S. А Linux уже и вправду не торт :(( у нас mm все никак не заработает… начинается сильный swapout на элементарных нагрузках…
  • +2

    Я понимаю, что ковыряние в ядре ваша специализация. Вы именно этим зарабатываете, но держать не LTS дистр на инфраструктурном сервере… Зачем?

    • +1
      Для тестирования CRIU нужно очень свежее ядро. У нас есть даже списочек патчей, которые так или иначе касаются CRIU https://criu.org/Upstream_kernel_commits. Тут можно заметить, что почти в каждом ядре появляется что-то новое, и мы хотим все это покрывать тестами.
      • 0
        Для тестирования CRIU нужно очень свежее ядро.

        Ну это же один сервер, ну или немного? Просто из первого обзаца сложилось впечатление, что в CI у вас одна только Fedora.

        • +1
          CRIU — проект небольшой. Пока нам для тестирования хватает двух серверов (x86_64) и travis-ci. Есть еще виртуалки под другие архитектуры, но там с ядрами мы экспериментов не ставим.

          К слову, у нас есть забавный эксперимент над трависом, когда мы там компиляем свое ядро и подменяем им существующее. Сейчас мы это используем для тестирования Linux-next
          https://travis-ci.org/avagin/criu/builds/252438980
  • +1
    Интересно а в bsd ядрах такие же проблемы?
    • +2

      Я думаю, такие проблемы во всех ядрах( Ядро все-таки довольно сложный програмный продукт.

      • +2
        Объём кода во всей BSD (ядро и всю базовая система) примерно равен объёму кода одного ядра Linux :-) Так что ядро BSD ковырять попроще :-)
    • +3
      Вообще сейчас перечитал статью еще раз и понял истину. Всетаки идеи open source работают и тут это наглядно видно. Обнаружен баг, обнаружены причины, дефект устранен(ну почти) и все довольны. В случае тех же ms было бы намного сложнее выявить проблему, еще сложнее достучаться и очень долго ждать когда это пофиксят. Тут же прям здесь и сейчас пусть и без пуша(как я понял) патча в гит ядра.
      • 0
        Вы имеете негативный опыт багрепортов в МС, или вам так просто кажется?
        • 0
          Имею разный опыт репортов в МС. Бывает, что пишешь, а с той стороны никого. Бывали случаи, когда находишь баг, но править его уже никто не хотел, боясь кого-нибудь сломать.
          • +1
            Если что, я думал что МС — это мейнстримое ядро линукс, а ней майкрасофт:-D
        • +1
          Пару раз приходилось и опыт крайне негативный.
          • 0
            В чем был негатив?
            • 0
              Довелось разок, давненько, столкнуться со странным поведением относительно новой виндовс виста. Подключен к ADSL роутеру компьютер с Windows XP и ноутбук с вистой. На компьютере всё работает нормально, а виста упорно твердит, что интернета нет. Обращение в службу поддержки МС привело к предложению к нам сначала получить в письменном виде справку от провайдера, что проблема не у них, и предоставить её в МС. После такой «поддержки» я больше никогда не пытался с ними что-либо решать.
      • +2
        Тут в соседней теме кажется проблема с ядром у ms. Посмотрим кто быстрее справится :)
        https://habrahabr.ru/post/332816/[perevod]-24-yadernyy-cpu--a-ya-ne-mogu-sd/
    • +1
      Нет в BSD таких проблем.
      У фри есть ветка HEAD — там бывает что то ломается, на ней сидят разработчики которые могут сами всё починить. Те кто не ищет приключений (те кому работу работать, жизнь жить и тп) её не ставит себе, кроме случаев когда в head есть какая то оч нужная фича которая не будет бэкпортирована.
      Есть ветки STABLE и RELEASE — туда обычно или бэкпортируется аккуратно. Оно изначально получается из HEAD, в которой отловили большинство багов и стабилизировали.

      Описанное в заметке это говнокодинг какой то, у нас во фряшечке я такого не видел.
      • +3
        Так в Linux тоже есть люди, которые такого не видели, это же не говорит, что такого нет. Ну, и здесь мы говорим про аналог вашего HEAD.
  • 0

    А не хотите перевести и запостить статью на каком-нибудь популярном
    англоязычном ресурсе? Автоматические тесты, насколько я знаю, есть у некоторых
    подсистем, типа файловых систем, неплохо было бы начать движение к объединению,
    интеграции и т.д.

    • +1
      Да, проблема известная. Прямо сейчас вижу здоровый тред, где народ обсуждает тесты для ядра в преддверии кернел самита. Может и переведем, посмотрим как настроение будет.
      • 0
        А мне кажется статья написана достаточно нездорово. В духе «вот мы и так и сяк а всё равно ничего не работает». Хотя вроде половина авторов статьи в ней же и участвует. Я вот почитал — думаю opensource действительно работает :) А если автор все таки не согласен — чёж там, слазьте на «стабильную» винду и радуйтесь
        • +2
          Мне кажется вы меня неправильно поняли. На винде если вы встретите баг, и вы не большая корпорация, вы ничего сделать не сможете. А здесь, мы имея ограниченные ресурсы, смогли победить все проблемы и последнюю неделю наш CI крутится, не течет и не падает. На самом деле вся прелесть opensource именно в этом. Любую ошибку можно исправить за счет собственного времени.

          Второй вывод можно сделать в сторону LTS версий. Да, там обычно не самое свежее ядро, но на то есть причины, и эта статья яркий пример этому. Обычно мы не собираем свои ядра и крутимся на том, что пришло от федоры, но иногда случаются вот такие черные полосы. Сразу скажу, это бывает не так часто. А на столько неприятная ситуация возникла впервые за 6 лет.
  • –1
    Господа авторы в качестве бреда, дайте расшифровку CRIU и CI, ну так типа возможно наверное будет логично, скажу вам по секрету не у всех столько времени, как у вас, чтобы гуглить, искать все ваши обозначения, так же хочу напомнить, что это не специфичный сайт по openvz, linux и поэтому было бы неплохо продумать этот вопрос, заранее благодарю,
    • +1
      Я рекомендую вам пойти научиться хорошим манерам, а потом приходите, я вам все расшифрую.
  • –1
    Благодарю за развернутый ответ.

Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

Самое читаемое Разработка