В проекте приведена работа по исследованию различных файловых систем в Linux на пример максимальной длины имени файлов и написанию патча для ядра для приведения данного параметра к единому значению.
Проверка файловых систем выполнялась на Ubuntu c версией ядра 5.8.0 с помощью стандартной библиотечной функции statfs, которая по пути до файла/директории позволяет узнать информацию о файловой системе в которой он располагается. Поле f_namelen содержит информацию о максимальном количестве байт, которое может занимать имя файла.
Командой truncate создавался файл размером 1 Гб, вызовом mkfs в этот файл добавлялась рассматриваемая файловая система, затем с помощью команды mount данный файл, с указанием типа файловой системы, монтировался в пустую директорию и на ней запускалась тестовая программа. После выполнения теста вызовом umount раздел отмонтировался и файл с директорией удалялись.
Был написан скрипт, который создает файлы с последовательно увеличивающейся длиной имени, пока команда truncate не завершится с ошибкой. Такое тестирование проводится для символов латиницы и кириллицы в имени.
Для корректной работы скрипта тестирования необходимо установить EEPM (Etersoft EPM package manager): EEPM.
Для данной файловой системы заявляется максимальная длина имени файла в 255 символов, учитывая устаревший способ кодирования, который до сих пор используется для FAT, с помощью 6 байт на символ, получаем ограничение в 1530 байт.
Результат работы тестовой программы:
tf_type: FAT 0x4d44
tf_namelen: 1530
Рассмотрим как это значение вычисляется в ядре:
f_namelen = (sbi->options.isvfat ? FAT_LFN_LEN : 12) * NLS_MAX_CHARSET_SIZE;
Константа FAT_LFN_LEN, равная 255 находится в файле include/uapi/linux/msdos_fs.h
NLS_MAX_CHARSET_SIZE находится в файле include/linux/nls.h и равняется 6, хотя с ноября 2003 года пятый и шестой байты в UTF-8 уже не используются при кодировании, для обеспечения совместимости с UTF-16.
Протестировали какая длина имени файла реально доступна при использовании символов латиницы и кириллицы:
Maximum FileName length with Latin characters is: 255
Maximum FileName length with Cyrillic characters is: 127
Таким образом, мы получили, что заявленное значение подразумевает использование в имени кодировки UTF-8.
Для данной файловой системы заявляется максимальная длина имени файла в 255 символов, учитывая устаревший способ кодирования, который до сих пор используется для exFAT, с помощью 6 байт на символ, получаем ограничение в 1530 байт.
Результат работы тестовой программы:
tf_type: FUSE 0x65735546
tf_namelen: 255
Файловая система exFAT поддерживается в ядре начиная с версии 5.4, до этого момента создание производилось с помощью FUSE. Удалили пакет exFAT-FUSE:
sudo apt-get autoremove exfat-fuse
После удаления пакета, создание рассматриваемой файловой системы стало невозможно.
Установили отдельно пакет exfatprogs:
epm --auto install exfatprogs
Запустили тестовую программу еще раз, получили следующие результаты:
tf_type: exFAT 0x2011bab0
tf_namelen: 1530
Рассмотрим, как это значение вычисляется в ядре:
f_namelen = EXFAT_MAX_FILE_LEN * NLS_MAX_CHARSET_SIZE;
Константа EXFAT_MAX_FILE_LEN равная 255 находится в файле fs/exfat/exfat_raw.h, а NLS_MAX_CHARSET_SIZE в include/linux/nls.h и равняется 6.
Протестировали какая длина имени файла реально доступна при использовании символов латиницы и кириллицы:
Maximum FileName length with Latin characters is: 255
Maximum FileName length with Cyrillic characters is: 255
Таким образом, мы убедились, что полученное в тестовой программе значение корректно и совпадает с заявленным.
Для данной файловой системы заявляется максимальная длина имени файла в 255 байт.
Результат работы тестовой программы:
tf_type: EXT4 0xef53
tf_namelen: 255
Рассмотрим как данное значение вычисляется в ядре:
f_namelen = EXT4_NAME_LEN;
Константа EXT4_NAME_LEN равная 255 находится в файле fs/exfat/ext4.h.
Протестировали какая длина имени файла реально доступна при использовании символов латиницы и кириллицы:
Maximum FileName length with Latin characters is: 255
Maximum FileName length with Cyrillic characters is: 127
Таким образом, мы убедились, что полученное в тестовой программе значение корректно и совпадает с заявленным.
Для данной файловой системы заявляется максимальная длина имени файла в 255 байт.
Для создания файловой системы установили пакет btrfs-progs:
epm --auto install btrfs-progs
Результат работы тестовой программы:
tf_type: BTRFS 0x9123683e
tf_namelen: 255
Рассмотрим как данное значение вычисляется в ядре:
f_namelen = BTRFS_NAME_LEN;
Константа BTRFS_NAME_LEN равная 255 находится в файле fs/btrfs/ctree.h.
Протестировали какая длина имени файла реально доступна при использовании символов латиницы и кириллицы:
Maximum FileName length with Latin characters is: 255
Maximum FileName length with Cyrillic characters is: 127
Таким образом, мы убедились, что полученное в тестовой программе значение корректно и совпадает с заявленным.
Для данной файловой системы заявляется максимальная длина имени файла в 255 символов.
На момент проведения тестирования файловая система NTFS поддерживается в ядре только в режиме чтения. Пакет, который позволяет создавать ее, поставляется вместе с ntfs-3g, реализующий работу с NTFS через FUSE, установили его:
epm --auto install ntfs-3g
Рассматриваемая файловая система монтируется только в виде блочного устройства. Нашли свободное петлевое устройство:
losetup -f
Привязали наш файл к нему, для взаимодействия с ним как с обычным блочным:
losetup $(losetup -f) ntfs.txt
Создали на данном устройстве NTFS, примонтировали его в директорию с указанием типа файловой системы и запустили тестовую программу, получили следующие результаты:
tf_type: FUSE 0x65735546
tf_namelen: 255
Протестировали какая длина имени файла реально доступна при использовании символов латиницы и кириллицы:
Maximum FileName length with Latin characters is: 255
Maximum FileName length with Cyrillic characters is: 255
Таким образом, мы убедились, что полученное в тестовой программе значение корректно и совпадает с заявленным.
Оказалось, что установленный пакет ntfs-3g перекрывает реализацию NTFS в ядре, так как имеет то же название типа при вызове mount. Установить отдельно пакет для создания NTFS не представлялось возможным, удалили его после создания файловой системы, примонтировали блочное устройство и запустили тестовую программу, получили следующие результаты:
tf_type: NTFS 0x5346544e
tf_namelen: 255
Рассмотрим как данное значение вычисляется в ядре:
f_namelen = NTFS_MAX_NAME_LEN;
Константа NTFS_MAX_NAME_LEN равная 255 находится в файле fs/ntfs/ntfs.h.
Протестировали какая длина имени файла реально доступна при использовании символов латиницы и кириллицы:
Maximum FileName length with Latin characters is: 0
Maximum FileName length with Cyrillic characters is: 0
Таким образом, мы убедились, что полученное в тестовой программе значение корректно и совпадает с заявленным.
Для данной файловой системы заявляется максимальная длина имени файла в 255 байт.
Для работы с ней установили пакет zfsutils-linux:
epm --auto install zfsutils-linux
Рассматриваемая файловая система может расположена на нескольких разделах, для этого предварительно создается пул и к нему уже подключаются разделы. Выбрали свободное петлевое устройство:
zfsBlock=`sudo losetup -f`
Привязали к нему файл, для задания непустого размера:
sudo losetup $zfsBlock zfs.txt
Создали пул на выбранном петлевом устройстве:
sudo zpool create -f zfsTestPool $zfsBlock
Задали точку монтирования в предварительно созданную пустую директорию для удобства тестирования:
sudo zfs set mountpoint=`pwd`/zfs zfsTestPool
Результат работы тестовой программы:
tf_type: ZFS 0x2fc12fc1
tf_namelen: 255
ZFS реализована как модуль для ядра Linux и входит в состав некоторых дистрибутивов(Ubuntu, Debian, Gentoo, ...). Рассмотрим как полученное значение длины вычисляется в самом модуле:
f_namelen = MAXNAMELEN - 1
Данное поле определяется в файле /module/os/linux/zfs/zfs_vfsops.c.
Константа MAXNAMELEN равная 256 находится в файле /include/sys/fs/zfs.h.
Протестировали какая длина имени файла реально доступна при использовании символов латиницы и кириллицы:
Maximum FileName length with Latin characters is: 255
Maximum FileName length with Cyrillic characters is: 127
Таким образом, мы убедились, что полученное в тестовой программе значение корректно и совпадает с заявленным.