Linux/InodeConv: различия между версиями

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


<blockquote>
<blockquote>
В настоящее время в сетевых файловых системах используются 64-битные и 32-битные системы????. Проблема в том, что многие программы для проверки существования файла используют функцию stat (), которая возвращает ошибку в 32-битных системах при переполнении полей структуры stat.
В настоящее время в сетевых файловых системах используются 64-битные и 32-битные системы????.
В настоящее время наблюдается активное сетевое взаимодействие 64-битных и 32-битных систем. Проблема в том, что многие программы для проверки существования файла используют функцию stat (), которая возвращает ошибку в 32-битных системах при переполнении полей структуры stat.
Данный патч позволяет решить проблему переполнения поля inode, сжимая его до 32бит.
Данный патч позволяет решить проблему переполнения поля inode, сжимая его до 32бит.


Строка 124: Строка 125:


<blockquote>
<blockquote>
Nowadays in network filesystems 64bit and 32bit systems are used. Due to this we have a compatibility problem - programs on 32bit systems have to operate with 64bit inodes.  
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.
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 many systems(e.g. fuse) - squashing inodes for 32systems.
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.
</blockquote>
</blockquote>

Версия 17:28, 13 февраля 2014

Задача

Описание задачи и альтернативный метод решения представлен здесь: http://wiki.etersoft.ru/Linux/ZeroInode

Squashing Inode

Для решения данной проблемы предлагается использование сжатия 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 необходимо руководствоваться следующими документами:

Необходимо оформить патч по приведенным требованиям.

Описание баги в mail-list

Здесь составлено описание баги в mail-list для glibc (на русском).

В настоящее время в сетевых файловых системах используются 64-битные и 32-битные системы????. В настоящее время наблюдается активное сетевое взаимодействие 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.