Linux/InodeConv: различия между версиями
Строка 1: | Строка 1: | ||
=Задача= | |||
Описание задачи и альтернативный метод решения представлен здесь: | Описание задачи и альтернативный метод решения представлен здесь: | ||
http://wiki.etersoft.ru/Linux/ZeroInode | http://wiki.etersoft.ru/Linux/ZeroInode | ||
=Squashing Inode for Glibc= | |||
Для решения данной проблемы предлагается использование сжатия inode. Похожий подход представлен здесь: | Для решения данной проблемы предлагается использование сжатия inode. Похожий подход представлен здесь: | ||
https://bugzilla.redhat.com/show_bug.cgi?id=872629. | https://bugzilla.redhat.com/show_bug.cgi?id=872629. |
Версия 18:13, 21 февраля 2014
Задача
Описание задачи и альтернативный метод решения представлен здесь: http://wiki.etersoft.ru/Linux/ZeroInode
Squashing Inode for Glibc
Для решения данной проблемы предлагается использование сжатия inode. Похожий подход представлен здесь: https://bugzilla.redhat.com/show_bug.cgi?id=872629. В нашем случае произведены следующие изменения
--- a/ports/sysdeps/unix/sysv/linux/generic/wordsize-32/getdents.c +++ b/ports/sysdeps/unix/sysv/linux/generic/wordsize-32/getdents.c @@ -26,10 +26,18 @@ #include <unistd.h> #include <sys/param.h> #include <sys/types.h> #include <sysdep.h> #include <sys/syscall.h> +static ino_t +squash_dir_inode (ino_t d_ino32, uint64_t d_ino64) +{ + d_ino32 ^= d_ino64 >> (sizeof (uint64_t) - sizeof (ino_t)) * 8; + return d_ino32; +} + /* Pack the dirent64 struct down into 32-bit offset/inode fields, and ensure that no overflow occurs. */ ssize_t @@ -87,10 +95,14 @@ __getdents (int fd, char *buf, size_t nbytes) outp->u.d_ino = d_ino; outp->u.d_off = d_off; - if ((sizeof (outp->u.d_ino) != sizeof (inp->k.d_ino) + if (sizeof (outp->u.d_ino) != sizeof (inp->k.d_ino) && outp->u.d_ino != d_ino) - || (sizeof (outp->u.d_off) != sizeof (inp->k.d_off) - && outp->u.d_off != d_off)) + { + /* Inode overflow. Squash it*/ + outp->u.d_ino = squash_dir_inode (outp->u.d_ino, d_ino); + } + if (sizeof (outp->u.d_off) != sizeof (inp->k.d_off) + && outp->u.d_off != d_off) { /* Overflow. If there was at least one entry before this one, return them without error, otherwise signal overflow. */
--- a/sysdeps/unix/sysv/linux/xstatconv.c +++ b/sysdeps/unix/sysv/linux/xstatconv.c @@ -20,6 +20,7 @@ #include <sys/stat.h> #include <kernel_stat.h> #include <kernel-features.h> #ifdef STAT_IS_KERNEL_STAT @@ -178,6 +179,14 @@ __xstat64_conv (int vers, struct kernel_stat *kbuf, void *ubuf) #endif } +static ino_t +squash_inode (ino_t ino32, ino64_t ino64) +{ + ino32 ^= ino64 >> (sizeof (ino64_t) - sizeof (ino_t)) * 8; + return ino32; +} + + int __xstat32_conv (int vers, struct stat64 *kbuf, struct stat *buf) { @@ -202,8 +211,7 @@ __xstat32_conv (int vers, struct stat64 *kbuf, struct stat *buf) if (sizeof (buf->st_ino) != sizeof (kbuf->st_ino) && buf->st_ino != kbuf->st_ino) { - __set_errno (EOVERFLOW); - return -1; + buf->st_ino = squash_inode (buf->st_ino, kbuf->st_ino); } } #else @@ -211,8 +219,7 @@ __xstat32_conv (int vers, struct stat64 *kbuf, struct stat *buf) if (sizeof (buf->st_ino) != sizeof (kbuf->st_ino) && buf->st_ino != kbuf->st_ino) { - __set_errno (EOVERFLOW); - return -1; + buf->st_ino = squash_inode (buf->st_ino, kbuf->st_ino); } #endif buf->st_mode = kbuf->st_mode;
Создание патча
Для создания патча для glibc необходимо руководствоваться следующими документами:
- Документация glibc
- Glibc Wiki - обратить внимание на пункт 5.
- Соглашение по оформлению кода конкретно для glibc
- Соглашение по оформлению кода для GNU
- Стандарт для вносимых изменений
- Manual page
- Багзилла - здесь необходимо создать багу
- Похожая бага
Необходимо оформить патч по приведенным требованиям.
Описание баги в mail-list
Здесь составлено описание баги в mail-list для glibc (на русском).
В настоящее время наблюдается активное сетевое взаимодействие 64-битных и 32-битных систем. Проблема в том, что многие программы для проверки существования файла используют функцию stat (), которая возвращает ошибку в 32-битных системах при переполнении полей структуры stat. Данный патч позволяет решить проблему переполнения поля inode, сжимая его до 32бит.
Есть и другие варианты решения:
1. Перекомпиляция программ с флагом сборки -D_FILE_OFFSET_BITS=64. Но этот подход может потребовать большой переделки программы.
2. Обнулять inode. Этот вариант плох тем, что некоторых программах есть проверка существования файла по inode: if (st_ino >= 0) ...
Nowadays we can observe active cooperation between 64bit and 32bit systems. Due to this we have a compatibility problem - programs on 32bit systems have to operate with 64bit inodes.
Most of these programs use stat to check out file's presence and don's use inodes themselves. Sometimes we could resolve this problem by means of rebuilding them with -D_FILE_OFFSET_BITS=64 flag.
But many of them can't be rebuilt. So there is another way that is used in other products which have such a problem(e.g. fuse) - squashing inodes for 32bit systems.