Linux/InodeConv

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

Задача

Описание задачи и альтернативный метод решения представлен здесь: 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 <stdio.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>
+#include <stdio.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 необходимо руководствоваться следующими документами:

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

Описание баги