Bug 28214

Summary: Системный вызов stat() для проверки файлов
Product: Sisyphus Reporter: Evgeny Sinelnikov <sin>
Component: aptAssignee: placeholder <placeholder>
Status: CLOSED FIXED QA Contact: qa-sisyphus
Severity: normal    
Priority: P3 CC: boyarsh, evg, glebfm, icesik, imz, iv, lav, ldv, led, mike, piastry, placeholder, real.altlinux.org, vsu
Version: unstable   
Hardware: all   
OS: Linux   
URL: http://bugs.etersoft.ru/show_bug.cgi?id=8869

Description Evgeny Sinelnikov 2012-12-11 21:35:17 MSK
Недавно столкнулся с проблемой некорректной работы apt по протоколу file:// на каталогах подключенных через CIFS. Выяснилось, что проблема проявляется на 32-битных системах, подключающих CIFS-каталоги с 64-битного сервера.

Проблема исследована в задаче ETER#8869:
http://bugs.etersoft.ru/show_bug.cgi?id=8869

"apt использует stat вызов для проверки доступности файла, что на 32 битной
машине падает, если номера айнодов 64 битные. Поэтому нужно либо использовать
stat64, либо компилировать с опцией -D_FILE_OFFSET_BITS=64. Так же есть вариант
использовать опцию монтирования noserverino. Проблема повторяет то, что у нас
было с WINE тут: http://bugs.etersoft.ru/show_bug.cgi?id=7302#c3."

Стоит отметить, что подобной проблеме подвержен, видимо, не только apt. Но и, например bash, у которого некорректно работает автодополнение по именам каталогов в цепочке каталогов, подключенных через CIFS.
Comment 1 Vitaly Lipatov 2012-12-18 15:27:41 MSK
Может быть надо рассмотреть принудительную сборку всего с -D_FILE_OFFSET_BITS=64? Получается, что ни одна программа без этого, использующая stat, работать толком не будет.
Хотя я и не понимаю, какое дело проверке доступности файла с помощью stat до номера inode. Мне всё же кажется, что это больше проблема функций, или ядра. NFS вот отлично умеет сворачивать номера inode в 32-битные, как я понял.

На самом деле основная наша задача по проблеме 64 inode у нас здесь:
http://bugs.etersoft.ru/show_bug.cgi?id=8420
Comment 2 Dmitry V. Levin 2012-12-18 16:44:58 MSK
Надо просто добавить AC_SYS_LARGEFILE.
Comment 3 Vitaly Lipatov 2012-12-20 18:26:53 MSK
(В ответ на комментарий №2)
> Надо просто добавить AC_SYS_LARGEFILE.
Но я так понимаю, что для 32-битных систем всё более вероятная ситуация иметь сервер на 64-битной платформе.

Возможно, должно быть принято более широкое решение, как обеспечить совместимость. то ли сжимать inode в файловых системах в ядре, то ли использовать 
FILE_OFFSET_BITS (stat64), то ли что-то ещё.

Кстати, на тему:
http://sandeen.net/wordpress/computers/the-world-wants-32-bit-inodes/
Comment 4 Dmitry V. Levin 2012-12-20 18:37:37 MSK
(In reply to comment #3)
> (В ответ на комментарий №2)
> > Надо просто добавить AC_SYS_LARGEFILE.
> Но я так понимаю, что для 32-битных систем всё более вероятная ситуация иметь
> сервер на 64-битной платформе.
> 
> Возможно, должно быть принято более широкое решение, как обеспечить
> совместимость. то ли сжимать inode в файловых системах в ядре, то ли
> использовать 
> FILE_OFFSET_BITS (stat64), то ли что-то ещё.

Достаточно просто добавить AC_SYS_LARGEFILE, который does the right thing.
Comment 5 Vitaly Lipatov 2012-12-22 02:45:30 MSK
(В ответ на комментарий №4)
...
> Достаточно просто добавить AC_SYS_LARGEFILE, который does the right thing.
А мы будем добавлять в sisyphus_check проверку на то, что 32-битный бинарник не использует 32-битный stat или будем ловить случайные глюки с разнообразными программами, при использовании 64-битного файлового сервера?
Comment 6 Dmitry V. Levin 2012-12-22 04:18:33 MSK
(In reply to comment #5)
> (В ответ на комментарий №4)
> ...
> > Достаточно просто добавить AC_SYS_LARGEFILE, который does the right thing.
> А мы будем добавлять в sisyphus_check проверку на то, что 32-битный бинарник не
> использует 32-битный stat или будем ловить случайные глюки с разнообразными
> программами, при использовании 64-битного файлового сервера?

Мы не будем добавлять в sisyphus_check такую проверку, ей там не место.
Практичнее добавить диагностику куда-нибудь в verify-elf.
Comment 7 Vitaly Lipatov 2012-12-28 13:11:43 MSK
(В ответ на комментарий №6)
> > А мы будем добавлять в sisyphus_check проверку на то, что 32-битный бинарник не
> > использует 32-битный stat или будем ловить случайные глюки с разнообразными
> > программами, при использовании 64-битного файлового сервера?
> 
> Мы не будем добавлять в sisyphus_check такую проверку, ей там не место.
> Практичнее добавить диагностику куда-нибудь в verify-elf.
Действительно. Тогда завёл на это отдельную задачу
https://bugzilla.altlinux.org/show_bug.cgi?id=28290
Comment 8 Dmitry V. Levin 2013-01-11 04:54:23 MSK
-D_FILE_OFFSET_BITS=64 это ABI change на x86 (затрагивающее как минимум /usr/include/apt-pkg/clean.h), придется менять soname.
Comment 9 at@altlinux.org 2013-01-11 13:06:30 MSK
Мужчины, на мой взгляд, вы пидорасы.  Какой смысол делать "проверку" на использование функций, которые используются по умолчанию?  Такая "проверка" накроет половину пакетов, и что тогда, вы их вручную будете исправлять?
Comment 10 Dmitry V. Levin 2013-01-12 03:03:50 MSK
(In reply to comment #9)
> Какой смысол делать "проверку" на
> использование функций, которые используются по умолчанию?  Такая "проверка"
> накроет половину пакетов, и что тогда, вы их вручную будете исправлять?

Напрашивается прямая аналогия:

Какой смысл добавлять -Wall в %optflags?  Такая "проверка" накроет больше половины пакетов, и что тогда, их тоже вручную исправлять?
Comment 11 at@altlinux.org 2013-01-12 05:00:23 MSK
Мужчины, получается, что у вас _все_ программы по умолчанию дефектные, т.к. они используют дефолтный ABI.  Довольно абсурдная ситуация.  Может тогда не использовать по умолчанию дефолтный ABI? :-)  Напишите тогда в апстрим glibc: "hey queers, нам пришла в голову fascinating idea!..."

И не понятно, почему программы падают. Если 64-битный i-node урезать до 32-битного, то упасть еще никто не должен.  Ядро отдает номера i-нодов, чтобы юзеру проще было идентифицировать файлы, но назад их не берёт.
Comment 12 Dmitry V. Levin 2013-01-12 06:06:26 MSK
(In reply to comment #11)
> Мужчины, получается, что у вас _все_ программы по умолчанию дефектные, т.к. они
> используют дефолтный ABI.  Довольно абсурдная ситуация.

Да, так исторически сложилось.  Впрочем, большинство GNU'шных и некоторое множество остальных программ используют AC_SYS_LARGEFILE корректно.  Так что сейчас уже далеко не все дефектные.

> Может тогда не
> использовать по умолчанию дефолтный ABI? :-)

Думаю, никому не надо объяснять, почему нельзя менять это умолчание.

> Напишите тогда в апстрим glibc:
> "hey queers, нам пришла в голову fascinating idea!..."

Самому себе предлагаешь написать?  Нет, это развлечение не по мне.

> И не понятно, почему программы падают.

В данном случае не падают, а просто работают неправильно - файлов не видят.

> Если 64-битный i-node урезать до
> 32-битного, то упасть еще никто не должен.  Ядро отдает номера i-нодов, чтобы
> юзеру проще было идентифицировать файлы, но назад их не берёт.

Чего гадать, когда можно просто в linux/fs/stat.c исходный код посмотреть.
Например, там написано, что stat(2) возвращает EOVERFLOW, когда st_ino, st_nlink или st_size недостаточного размера.
Comment 13 at@altlinux.org 2013-01-12 11:10:58 MSK
Точно, linux/fs/stat.c отказывается урезать длинные номера i-нодов.  Но классическая реализация фс предполагает, что i-ноды выделяются заранее и нумеруются последовательно (и потом повторно используются), в частности, корневой каталог фс имеет i-нод примерно равный два (какой точно забыл) и т.д.  Так что в классической реализации номера i-нодов имеют право переполинться, только если файлов на диске больше 4 млрд.  Если каждый i-нод занимает на диске 128 байтов, то в сумме i-ноды на такой фс займут 0.5Тб.  Поэтому идея 32-битного ABI по умолчанию выглядит в общем-то жизнеспособной.  А почему нельзя переключиться на 64-битный ABI по умолчанию?
Comment 14 Sergey Vlasov 2013-01-12 17:07:31 MSK
Действительно, для классической реализации (например, ext4 в текущем состоянии) особых проблем нет (при значении по умолчанию inode_ratio = 16384 32-битных номеров inode хватит для ФС размером до 64 ТБ). Однако далеко не все ФС имеют подобную структуру, позволяющую легко вписываться в ограничения на номера inode.

Например, в btrfs в качестве номера inode используется внутренний идентификатор объекта ФС, при этом идентификаторы назначаются последовательно по возрастанию и не используются повторно, так что переполнение 32-битного номера inode произойдёт после выполнения около 2^32 операций создания файлов.

Наиболее проблемная в этом плане ФС из популярных, видимо, xfs, где используется следующий формат номера inode:

/*
 * Inode number format:
 * low inopblog bits - offset in block
 * next agblklog bits - block number in ag
 * next agno_log bits - ag number
 * high agno_log-agblklog-inopblog bits - 0
 */

При этом по умолчанию inopblog = 4 (в блок размером 4К помещается 16 записей inode размером 256 байт), а agblklog + agno_log — это примерно число битов, необходимое для адресации всех блоков ФС; в результате получается, что 32-битного номера inode в случае произвольного размещения inode достаточно лишь при размере ФС не более 1 ТБ.

Для совместимости в xfs в ядрах до 3.7 по умолчанию не разрешалось размещение inode за пределами области, в которой номера inode помещаются в 32 бита, однако такой режим, во-первых, может снижать производительность (поскольку не удаётся разместить inode рядом с данными файла), во-вторых, мог приводить к невозможности создания файлов при видимом наличии свободного места, если вся область ниже 1 ТБ оказывалась заполненной. Начиная с ядра 3.7 опция inode64 для xfs используется по умолчанию, а для включения режима совместимости добавлена опция монтирования inode32 (также можно переключать эти режимы на смонтированной ФС, что повлияет на размещение inode для создаваемых после переключения файлов).
Comment 15 Dmitry V. Levin 2013-01-12 21:09:14 MSK
(In reply to comment #13)
> А почему нельзя переключиться на 64-битный ABI по умолчанию?

64-битный ABI - это не столько ino_t, сколько off_t.  Когда ты включаешь этот 64-битный ABI, меняются не только объекты типа ino_t, которых относительно немного, но и объекты типа off_t, которые встречаются на каждом шагу.  В каждом случае нужно убедиться, что 64-битный тип не преобразуется к 32-битному типу, что нигде указатели на 32-битные типы не обрабатываются как указатели на 64-битные типы, и наоборот.  В общем, такие изменения нельзя делать неявно.
Comment 16 Repository Robot 2013-01-30 07:00:52 MSK
apt-0.5.15lorg2-alt42 -> sisyphus:

* Thu Jan 10 2013 Dmitry V. Levin <ldv@altlinux> 0.5.15lorg2-alt42
- Fixed and enabled LFS support (closes: #28214).