Linux/VLFN

Материал из Etersoft wiki
Перейти к навигацииПерейти к поиску

VLFN(Very Long FileName) - проблема, заключающаяся в том, что в GNU/Linux применено ограничение в 255 байт на длину имени файла, что при использовании UTF-8 даёт для русских букв не более 127 символов.

Длинные имена файлов в Linux

Увеличение длин имен файлов в Linux.

Имена файлов в Windows и Linux

В Windows для именования файлов принята кодировка UTF-16, то есть каждый символ в названии файла кодируется двумя байтами (16 бит). Максимальная длина имени файла — 255 символов (510 байт). В Linux же для именования файлов принята кодировка UTF-8, при этом максимальная длина файла составляет 255 байт (а не символов).

Постановка задачи

Так как в UTF-8 для кодирования русских букв используется два байта, то максимальная длина имени файла, состоящего из русских букв, фактически составляет 127 символов. В связи с этим появляется проблема - длинные имена файлов (от 128 до 255 русских символов) не влезают в установленные для них ограничения в Linux.

Упоминания данной проблемы:

Решение

Предложенное решение - необходимо увеличить возможную длину файлов в Linux.
Выбранная длина нового максимального предела имени файла - 1023 байта.
Причины выбора:

  • нет привязки к Windows, поэтому нет необходимости задавать размер ровно 511 байт;
  • имя файла задается с запасом, что позволит адаптировать ОС и ФС к иероглифической, к примеру письменности, где знаки могут занимать в районе 4 байт.

Уже сделано

Был проведен тест файловой системы NTFS. Оказалось, что на данной можно создавать файлы с длинным русским именем, из чего следовало, что ограничение задается самой ФС, а не ядром или библиотекой glibc: https://bugs.etersoft.ru/show_bug.cgi?id=9266
Было решено выбрать файловую систему, которую легче всего было бы адаптировать для решения данной проблемы. Затем было проведено сравнение самых распространенных и перспективных файловых систем: http://wiki.etersoft.ru/Comparison_of_file_systems Стоит рассмотреть такие системы как btrfs, xfs, ext4.
В итоге, благодаря своей гибкости и динамичности своего развития, была выбрана файловая система BTRFS.

BTRFS

B TRee File System - файловая система, основанная на структуре Б-деревьев и работающая по принципу «копирование при записи».

Изменения

Изначально изменен предел BTRFS_NAME_LEN, заданный в файле /fs/btrfs/ctree.h. Аналогичный предел был изменен в пакете BTRFS-progs.
Изменения:

diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index d6dd49b..3ae04d0 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -154,7 +154,7 @@ struct btrfs_ordered_sum;
  * we can actually store much bigger names, but lets not confuse the rest
  * of linux
  */
-#define BTRFS_NAME_LEN 255
+#define BTRFS_NAME_LEN 1023

 /*
  * Theoretical limit is larger, but we keep this down to a sane
diff --git a/include/linux/compat.h b/include/linux/compat.h
index 7f0c1dd..9bbf0d9 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -202,7 +202,7 @@ struct compat_dirent {
        u32             d_ino;
        compat_off_t    d_off;
        u16             d_reclen;
-       char            d_name[256];
+       char            d_name[1024];
 };

 struct compat_ustat {
diff --git a/include/uapi/linux/limits.h b/include/uapi/linux/limits.h
index 2d0f941..ca17cbe 100644
--- a/include/uapi/linux/limits.h
+++ b/include/uapi/linux/limits.h
@@ -8,7 +8,7 @@
 #define LINK_MAX         127   /* # links a file may have */
 #define MAX_CANON        255   /* size of the canonical input queue */
 #define MAX_INPUT        255   /* size of the type-ahead buffer */
-#define NAME_MAX         255   /* # chars in a file name */
+#define NAME_MAX        1023   /* # chars in a file name */
 #define PATH_MAX        4096   /* # chars in a path name including nul */
 #define PIPE_BUF        4096   /* # bytes in atomic write to a pipe */
 #define XATTR_NAME_MAX   255   /* # chars in an extended attribute name */

Тестирование

Проведено тестирование основной функциональности новой файловой системы. Для граничных значение - 1024 и 1023 байта:

  • При измененном ядре и измененной программе форматирования:
Testing glibc functions with 1023-byte filename
FAILED: 0, PASSED: 20

Testing glibc functions with 1024-byte filename
FAILED: 0, PASSED: 20
  • При оригинальной версии программы для форматирования:
Testing glibc functions with 1023-byte filename

[root@host-35 btrfs]# /home/guest/glibc_vlfn_test 
Testing glibc functions with 1023-byte filename
FAILED: 0, PASSED: 20

Testing glibc functions with 1024-byte filename
FAILED: 0, PASSED: 20


  • При оригинальном ядре и измененной программе форматирования:
Testing glibc functions with 1023-byte filename
Error in line:190; file: glibc_vlfn_test.c: File name too long
Error in line:191; file: glibc_vlfn_test.c: File name too long
Error in line:192; file: glibc_vlfn_test.c: File name too long
Error in line:193; file: glibc_vlfn_test.c: File name too long
Error in line:194; file: glibc_vlfn_test.c: File name too long
Error in line:195; file: glibc_vlfn_test.c: File name too long
Error in line:196; file: glibc_vlfn_test.c: Success
Error in line:197; file: glibc_vlfn_test.c: File name too long
Error in line:198; file: glibc_vlfn_test.c: File name too long
Error in line:201; file: glibc_vlfn_test.c: File name too long
Error in line:202; file: glibc_vlfn_test.c: No such file or directory
Error in line:203; file: glibc_vlfn_test.c: File name too long
Error in line:204; file: glibc_vlfn_test.c: File name too long
Error in line:205; file: glibc_vlfn_test.c: File name too long
Error in line:206; file: glibc_vlfn_test.c: File name too long
Error in line:207; file: glibc_vlfn_test.c: No such file or directory
Error in line:208; file: glibc_vlfn_test.c: File name too long
Error in line:209; file: glibc_vlfn_test.c: File name too long
Error in line:210; file: glibc_vlfn_test.c: Success
Error in line:211; file: glibc_vlfn_test.c: File name too long
FAILED: 20, PASSED: 0

Testing glibc functions with 1024-byte filename
FAILED: 0, PASSED: 20

Программа для тестирования доступна тут: git.eter:/people/reprofy/public/glibc_vlfn_test.git

Применение

Для того, чтобы использовать файловую систему BTRFS с увеличенным пределом имени файла, необходимо:

  1. Установить исправленную версию ядра ( git.eter:/people/reprofy/packages/kernel_sis.git -> btrfs_new_bound );
  2. Отформатировать дисковый раздел, используя исправленную версию btrfs-progs ( git.eter:/people/reprofy/public/btrfs_progs.git -> filename_bound );
  3. Для обеспечения полной функциональности необходимо изменить предел в файле limits.h:
    1. Установить исправленный пакет kernel-source-3.9 ( git.eter:/people/reprofy/public/kernel_source_3.9.git -> namelength_increased );
    2. Установить пакет glibc-kernheaders(из репозитория git.alt );

Glibc

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

Тестирование mc

При использовании mc было обнаружено, что несмотря на исправленные пределы в файловой системе, midnight comander не отображает длинные имена файлов. Как оказалось далее, mc берет значения констант из файла /usr/include/linux/limits.h. Последний, в свою очередь, принадлежит пакету glibc-kernheaders, который требует среди зависимостей пакет kernel-source-3.9. Исправив в kernel-source файл limits.h, собрав и установив пакет на виртуальную машину, а затем собрав и установив glibc-kernheaders, удалось добиться изменения файла /usr/include/linux/limits.h. После чего, вновь собранный mc стал корректно отображать длинные имена.