Bug 8420

Summary: Надо разобраться с поддержкой 64-битных inode на 32-битных системах
Product: [Внутреннее (Etersoft)] Отдел серверных решений Reporter: Vitaly Lipatov <lav>
Component: ОбщееAssignee: Pavel Shilovsky <piastry>
Status: CLOSED FIXED QA Contact: Vitaly Lipatov <lav>
Severity: minor    
Priority: P4 CC: anton, baraka, danil, mid, sin
Version: не указана   
Target Milestone: ---   
Hardware: PC   
OS: All   
Whiteboard:
Заявки RT: Связано с:
Дата напоминания:
Bug Depends on:    
Bug Blocks: 9175    
Deadline: 2013-08-31   

Description Vitaly Lipatov 2012-04-28 01:33:07 MSK
Надо разобраться, где существует проблема с 64-битными inode.
1. NFS вроде как по умолчанию их передаёт.
2. Локальные файловые системы используют 64-битный номер.
3. CIFS оперирует 64-битным номером

Проблема проявляется только с glusterfs. Это очень странно, и возможно это исправимая бага? Хотя они что-то писали про 64 бита. Тогда нечего клиента на 32 бита собирать...

На 32-битных системах приходится явно или неявно использовать вызов stat64 и прочие подобные, чтобы иметь возможность оперировать с большими файлами. Не знаю, как это влияет на получаемый через stat номер inode.

http://sandeen.net/wordpress/computers/the-world-wants-32-bit-inodes/

На самом деле для нас может оказаться проще окончательно перейти на 64-битные системы. Нас ничего не держит, у нас только 2 сервера таких осталось (server и cellar).
Comment 1 Vitaly Lipatov 2012-04-28 13:23:32 MSK
Я вижу ситуацию вот так:
Although today linux kernel VFS layer is fixed to
handle 64 bit inode number, applications might still using 32 bit stat()
to access inode numbers could break.

http://www.mail-archive.com/linux-ext4@vger.kernel.org/msg01288.html
Comment 2 Pavel Shilovsky 2012-04-28 18:36:19 MSK
Обнаружилась возможная причина проблемы. FUSE модуль по таймауту возвращает то корректное 64 битное значение, то обрезанное 32 битное. Пути решения проблемы возможно следующие:
1) Исправить FUSE модуль, чтобы он возвращал всегда одно и тоже значение.
2) Поправить Gluster клиент, чтобы он пересылал сразу обрезанное значение модулю FUSE.
Comment 3 Pavel Shilovsky 2012-04-28 23:36:51 MSK
Создал и протестировал патч, исправляющий работу FUSE, - mc работает.
Comment 4 Pavel Shilovsky 2012-04-29 10:40:32 MSK
Работал над улучшением патча.
Comment 5 Pavel Shilovsky 2012-05-04 14:00:44 MSK
Провёл rebase патча на последний тэг v3.4-rc5, проверил собираемость, отправил в рассылки fuse-devel и linux-fsdevel.
Comment 6 Pavel Shilovsky 2012-05-10 20:08:27 MSK
Получил комментарии по патчу. Патч не приняли - в аптрим больше нравится вариант возвращения 64 битного айнода независимо от платформы, который был уже мною реализовал как пробный вариант ранее. 

Работал над новым вариантом патча. Как и ранее с ним есть одна проблема - не работает mcview c существующими файлами у которых айнод номер не умещается в 32 бита. Причина тому не понятна, так как даже если скопировать или создать новый файл с таким же большим айнод номером, mcview работает корректно.

В любом случае, патч исправляет проблему возвращения различных айнод номеров. Как только согласую с апстрим, можно будет тестировать у нас в рабочих условиях.
Comment 7 Pavel Shilovsky 2012-05-14 19:33:52 MSK
(В ответ на comment #6)
> В любом случае, патч исправляет проблему возвращения различных айнод номеров.
> Как только согласую с апстрим, можно будет тестировать у нас в рабочих
> условиях.

Патч в астрим:
http://git.kernel.org/?p=linux/kernel/git/mszeredi/fuse.git;a=commitdiff;h=45c72cd73c788dd18c8113d4a404d6b4a01decf1
Comment 8 Pavel Shilovsky 2012-05-25 17:23:00 MSK
(В ответ на comment #6)
> 
> Работал над новым вариантом патча. Как и ранее с ним есть одна проблема - не
> работает mcview c существующими файлами у которых айнод номер не умещается в 32
> бита. Причина тому не понятна, так как даже если скопировать или создать новый
> файл с таким же большим айнод номером, mcview работает корректно.
> 
Выяснил, что не работает корректно less - при чём, если менять некоторые байты в файле, less работать начинает. mcview так же. Видимо проблема не относится напрямую к номерам айнодов.
Comment 9 Pavel Shilovsky 2012-06-09 11:28:58 MSK
Патч в основной ветке ядра:
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=commit;h=45c72cd73c788dd18c8113d4a404d6b4a01decf1

Связался с разработчиком по поводу отправки патча в stable-ветки, получил согласие. Проверил совместимость патча с текущими stable-ветками, отправил в stable@vger.kernel.org.
Comment 10 Pavel Shilovsky 2012-06-20 16:17:10 MSK
Патч в ядрах v3.0.35, v3.2.21, v3.4.3.
Comment 11 Pavel Shilovsky 2012-11-02 19:53:16 MSK
Занимался проблемой продвижения нашего патча в OpenVZ ядро. Создал баг:
https://bugzilla.redhat.com/show_bug.cgi?id=872629
Comment 12 Pavel Shilovsky 2012-12-19 23:30:46 MSK
Бага в альтовской багзилле: https://bugzilla.altlinux.org/show_bug.cgi?id=28214.
Comment 13 Vitaly Lipatov 2012-12-20 18:27:58 MSK
(В ответ на comment #9)
> Патч в основной ветке ядра:
Хорошо бы понять, какой правильный путь: исправить все ФС в ядре, чтобы они сжимали номер inode, или все программы надо обязать использовать stat64 (-D_FILE_OFFSET_BITS=64)
Насколько я понимаю, в случае 32-битного контейнера на 64-битной системе для локальных ФС этой проблемы нет.

Сейчас решение выглядит больше похожим на хак. Хочется проблему либо решить глобально, либо описать все места её проявления.
Comment 14 Vitaly Lipatov 2012-12-28 13:13:23 MSK
Добавил в ALT задачу на добавление проверки использования функций stat
https://bugzilla.altlinux.org/show_bug.cgi?id=28290
Comment 15 Pavel Shilovsky 2012-12-29 02:51:53 MSK
Пропатчил код FUSE в OVZ ядре:
http://git.etersoft.ru/people/piastry/packages/?p=cifs-2.6.git;a=shortlog;h=refs/heads/kernel-image-ovz-el
Comment 16 Pavel Shilovsky 2013-03-30 20:33:50 MSK
Создал багу в багзилле альта (копия баги https://bugzilla.redhat.com/show_bug.cgi?id=872629):
https://bugzilla.altlinux.org/show_bug.cgi?id=28767
Comment 17 Pavel Shilovsky 2013-04-01 09:15:50 MSK
(В ответ на comment #16)
> Создал багу в багзилле альта (копия баги
> https://bugzilla.redhat.com/show_bug.cgi?id=872629):
> https://bugzilla.altlinux.org/show_bug.cgi?id=28767
Бага в багзилле альта исправлена, версия ядра - 2.6.32-alt85
Comment 18 Pavel Shilovsky 2013-06-12 15:11:06 MSK
В Red Hat бага исправлена в kernel-2.6.32-381.el6. Данная бага себя исчерпала, выставляю решена.
Comment 19 Vitaly Lipatov 2013-06-12 16:31:37 MSK
(В ответ на comment #14)
> Добавил в ALT задачу на добавление проверки использования функций stat
> https://bugzilla.altlinux.org/show_bug.cgi?id=28290

rpm-4.0.4-alt100.60 -> sisyphus:

* Fri Jan 11 2013 Dmitry V. Levin <ldv@altlinux> 4.0.4-alt100.60
- verify-elf: implemented LFS check (closes: #28290).

(В ответ на comment #18)
> В Red Hat бага исправлена в kernel-2.6.32-381.el6. Данная бага себя исчерпала,
> выставляю решена.
Глобальная проблема с 64-битными инодами на 32-битных системах превратилась в патч для fuse...

Ну ладно, закрываем, до новых звоночков. Вот как /home на gluster переведём, всё сразу станет ясно :)
Comment 20 Vitaly Lipatov 2013-06-27 23:06:54 MSK
Внезапно выяснилось, что rpm перестал понимать пакеты, выложенные в /var/ftp/pub.

# LANG=C rpm --checksig /var/ftp/pub/Etersoft/CIFS@Etersoft/5.4.7/sources/etercifs-5.4.7-alt1.src.rpm 
error: /var/ftp/pub/Etersoft/CIFS@Etersoft/5.4.7/sources/etercifs-5.4.7-alt1.src.rpm: rpmReadSignature failed

Небольшое расследование выявило, что у файла inode >4ГБ:
это видно по вызову из rpm:
fstat64(3</var/ftp/pub/Etersoft/CIFS@Etersoft/5.4.7/sources/etercifs-5.4.7-alt1.src.rpm>, {st_dev=makedev(253, 0), st_ino=4496308953, st_mode=S_IFREG|0644, st_nlink=1, st_uid=1706, st_gid=100, st_blksize=4096, st_blocks=15592, st_size=7981458, st_atime=2013/06/27-22:11:08, st_mtime=2013/06/27-22:19:54, st_ctime=2013/06/27-22:19:54}) = 0

и просто
# stat /var/ftp/pub/Etersoft/CIFS@Etersoft/5.4.7/sources/etercifs-5.4.7-alt1.src.rpm 
  Размер: 7981458   	Блоков: 15592      Блок В/В: 4096   обычный файл
Устройство: fd00h/64768d	Inode: 4496308953  Ссылки: 1

# mount 
/dev/mapper/storage-ftp on /var/ftppub type xfs (rw,nosuid,noatime,inode64,noquota)

Параметр inode64 не задавался явно при монтировании.
Из man mount:
       inode64
              Indicates that XFS is allowed to create inodes at any location in the filesystem, including those which  will  result  in  inode
              numbers  occupying  more  than  32  bits of significance.  This is provided for backwards compatibility, but causes problems for
              backup applications that cannot handle large inode numbers.

Вот из мана по mkfs.xfs:
XFS uses 64-bit inode numbers internally; however, the number of significant bits in an inode number is affected by filesystem geometry. In practice, filesystem size and inode size are the predominant factors. The Linux kernel (on 32 bit hardware platforms) and most applications cannot currently handle inode numbers greater than 32 significant bits, so if no inode size is given on the command line, mkfs.xfs will attempt to choose a size such that inode numbers will be < 32 bits.

При этом через NFS на 64-битной системе (builder64) всё работает.

Поскольку в 32-битном ядре нет проблем с 64-битными inode, я прихожу к выводу, что проблема в rpm.
Comment 21 Vitaly Lipatov 2013-06-27 23:21:19 MSK
Вот что нашлось про XFS:
https://bugzilla.altlinux.org/show_bug.cgi?id=28214#c14

Комментарий #14 от Sergey Vlasov 2013-01-12 17:07:31 (-) [ответить]

Действительно, для классической реализации (например, 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 22 Vitaly Lipatov 2013-06-27 23:29:53 MSK
Завёл багу на rpm:
https://bugzilla.altlinux.org/show_bug.cgi?id=29117
Comment 23 Vitaly Lipatov 2013-07-05 00:41:27 MSK
Выявилась небольшая особенность при использовании glusterfs (можно нас поздравить, мы перевели /var/ftp/pvt и /var/ftp/tmp на неё). FUSE исправлен, и теперь он ведёт себя в зависимости от системы. Но теперь я наткнулся на то, что мы традиционно монтируем ресурс один раз в host-систему, а дальше просто bind'им его в контейнеры.
И получается, что мы получаем 64-битный FUSE в 32-битной системе, и она не старается сокращать inode.

Дальше я подумал, раз эта замечательная функция stat (которую обычно используют узнать размер файла, но не могут, потому что в ней проверяется, влезает ли inode в 32-бита) делает проверку на inode, может быть это она должна сворачивать inode в 32 бита? Это решит проблему сразу со всеми программами.
Может быть надо по такому пути пойти? Потому что подход пересобрать все программы с поддержкой LFS далеко не сразу реализуем.
Comment 24 Vitaly Lipatov 2013-11-16 17:54:22 MSK
Закрываю, а то бага слишком ни о чём.

Общее решение делается там:
Сделать обнуление длинных inode в 32-битных функциях
https://bugs.etersoft.ru/show_bug.cgi?id=9552

Вопрос, во что превращать inode (в ноль или в сжатое значение), остаётся открытым для дискуссии. Мне всё равно, лишь бы работало :)
Comment 25 Anton Agapov 2014-03-14 16:53:56 MSK
Дополнительная информация.

В версии glusterfs 3.4.2 поддерживается опция nfs.enable-ino32:

For 32-bit nfs clients or applications that do not support 64-bit inode numbers or large files. Use this
option from the CLI to make Gluster NFS return 32-bit inode numbers instead. Applications that will benefit are those that were either:

Built 32-bit and run on 32-bit machines.
Built 32-bit on 64-bit systems.
Built 64-bit but use a library built 32-bit, especially relevant for python and perl scripts.
This option is disabled by default so NFS returns 64-bit inode numbers by default. Either of the conditions above can lead to application on Linux NFS clients failing with "Invalid argument" or "Value too large for defined data type" errors.

(по умолчанию, выключена)

Эта опция может быть активирована как на томе, так и на клиенте. Однако она имеет смысл при активированном nfs. На ftp-tmp, например, заблокировано.
Comment 26 Vitaly Lipatov 2014-11-22 02:31:54 MSK
Закрываю решённые более 180 дней назад.