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: | Связано с: | 7877 9552 | |
Дата напоминания: | |||
Bug Depends on: | |||
Bug Blocks: | 9175 | ||
Deadline: | 2013-08-31 |
Description
Vitaly Lipatov
2012-04-28 01:33:07 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 Обнаружилась возможная причина проблемы. FUSE модуль по таймауту возвращает то корректное 64 битное значение, то обрезанное 32 битное. Пути решения проблемы возможно следующие: 1) Исправить FUSE модуль, чтобы он возвращал всегда одно и тоже значение. 2) Поправить Gluster клиент, чтобы он пересылал сразу обрезанное значение модулю FUSE. Создал и протестировал патч, исправляющий работу FUSE, - mc работает. Работал над улучшением патча. Провёл rebase патча на последний тэг v3.4-rc5, проверил собираемость, отправил в рассылки fuse-devel и linux-fsdevel. Получил комментарии по патчу. Патч не приняли - в аптрим больше нравится вариант возвращения 64 битного айнода независимо от платформы, который был уже мною реализовал как пробный вариант ранее. Работал над новым вариантом патча. Как и ранее с ним есть одна проблема - не работает mcview c существующими файлами у которых айнод номер не умещается в 32 бита. Причина тому не понятна, так как даже если скопировать или создать новый файл с таким же большим айнод номером, mcview работает корректно. В любом случае, патч исправляет проблему возвращения различных айнод номеров. Как только согласую с апстрим, можно будет тестировать у нас в рабочих условиях. (В ответ на comment #6) > В любом случае, патч исправляет проблему возвращения различных айнод номеров. > Как только согласую с апстрим, можно будет тестировать у нас в рабочих > условиях. Патч в астрим: http://git.kernel.org/?p=linux/kernel/git/mszeredi/fuse.git;a=commitdiff;h=45c72cd73c788dd18c8113d4a404d6b4a01decf1 (В ответ на comment #6) > > Работал над новым вариантом патча. Как и ранее с ним есть одна проблема - не > работает mcview c существующими файлами у которых айнод номер не умещается в 32 > бита. Причина тому не понятна, так как даже если скопировать или создать новый > файл с таким же большим айнод номером, mcview работает корректно. > Выяснил, что не работает корректно less - при чём, если менять некоторые байты в файле, less работать начинает. mcview так же. Видимо проблема не относится напрямую к номерам айнодов. Патч в основной ветке ядра: http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=commit;h=45c72cd73c788dd18c8113d4a404d6b4a01decf1 Связался с разработчиком по поводу отправки патча в stable-ветки, получил согласие. Проверил совместимость патча с текущими stable-ветками, отправил в stable@vger.kernel.org. Патч в ядрах v3.0.35, v3.2.21, v3.4.3. Занимался проблемой продвижения нашего патча в OpenVZ ядро. Создал баг: https://bugzilla.redhat.com/show_bug.cgi?id=872629 Бага в альтовской багзилле: https://bugzilla.altlinux.org/show_bug.cgi?id=28214. (В ответ на comment #9) > Патч в основной ветке ядра: Хорошо бы понять, какой правильный путь: исправить все ФС в ядре, чтобы они сжимали номер inode, или все программы надо обязать использовать stat64 (-D_FILE_OFFSET_BITS=64) Насколько я понимаю, в случае 32-битного контейнера на 64-битной системе для локальных ФС этой проблемы нет. Сейчас решение выглядит больше похожим на хак. Хочется проблему либо решить глобально, либо описать все места её проявления. Добавил в ALT задачу на добавление проверки использования функций stat https://bugzilla.altlinux.org/show_bug.cgi?id=28290 Пропатчил код FUSE в OVZ ядре: http://git.etersoft.ru/people/piastry/packages/?p=cifs-2.6.git;a=shortlog;h=refs/heads/kernel-image-ovz-el Создал багу в багзилле альта (копия баги https://bugzilla.redhat.com/show_bug.cgi?id=872629): https://bugzilla.altlinux.org/show_bug.cgi?id=28767 (В ответ на comment #16) > Создал багу в багзилле альта (копия баги > https://bugzilla.redhat.com/show_bug.cgi?id=872629): > https://bugzilla.altlinux.org/show_bug.cgi?id=28767 Бага в багзилле альта исправлена, версия ядра - 2.6.32-alt85 В Red Hat бага исправлена в kernel-2.6.32-381.el6. Данная бага себя исчерпала, выставляю решена. (В ответ на 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 переведём, всё сразу станет ясно :) Внезапно выяснилось, что 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. Вот что нашлось про 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 для создаваемых после переключения файлов). Завёл багу на rpm: https://bugzilla.altlinux.org/show_bug.cgi?id=29117 Выявилась небольшая особенность при использовании glusterfs (можно нас поздравить, мы перевели /var/ftp/pvt и /var/ftp/tmp на неё). FUSE исправлен, и теперь он ведёт себя в зависимости от системы. Но теперь я наткнулся на то, что мы традиционно монтируем ресурс один раз в host-систему, а дальше просто bind'им его в контейнеры. И получается, что мы получаем 64-битный FUSE в 32-битной системе, и она не старается сокращать inode. Дальше я подумал, раз эта замечательная функция stat (которую обычно используют узнать размер файла, но не могут, потому что в ней проверяется, влезает ли inode в 32-бита) делает проверку на inode, может быть это она должна сворачивать inode в 32 бита? Это решит проблему сразу со всеми программами. Может быть надо по такому пути пойти? Потому что подход пересобрать все программы с поддержкой LFS далеко не сразу реализуем. Закрываю, а то бага слишком ни о чём. Общее решение делается там: Сделать обнуление длинных inode в 32-битных функциях https://bugs.etersoft.ru/show_bug.cgi?id=9552 Вопрос, во что превращать inode (в ноль или в сжатое значение), остаётся открытым для дискуссии. Мне всё равно, лишь бы работало :) Дополнительная информация. В версии 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, например, заблокировано. Закрываю решённые более 180 дней назад. |