Todo lo que debes saber sobre inodos en Linux

Introducción

El sistema de archivos de Linux se basa en inodos. Estas piezas vitales del funcionamiento interno del sistema de archivos a menudo se malinterpretan. Veamos exactamente qué son y qué hacen.

Los elementos de un sistema de archivos

Por definición, un sistema de archivos necesita almacenar archivos, y también contienen directorios. Los archivos se almacenan dentro de los directorios, y estos directorios pueden tener subdirectorios.

Algo, en algún lugar, tiene que registrar dónde se encuentran todos los archivos dentro del sistema de archivos. Se debe registrar cómo se llaman, a qué cuentas pertenecen, qué permisos tienen y mucho más. Esta información se llama metadatos porque son datos que describen otros datos.

En el sistema de archivos Linux ext4, las estructuras de inodo y directorio trabajan juntas. Esto para proporcionar un marco subyacente que almacena todos los metadatos para cada archivo y directorio. Hacen que los metadatos estén disponibles para cualquier persona que lo requiera. Por ejemplo, para el kernel, las aplicaciones de usuario, o utilidades de Linux, tales como lsstat, y df.

Inodos y tamaño del sistema de archivos

Si bien es cierto que hay un par de estructuras, un sistema de archivos requiere mucho más que eso. Hay miles y miles de cada estructura. Cada archivo y directorio requiere un inodo, y debido a que cada archivo está en un directorio, cada archivo también requiere una estructura de directorio. Las estructuras de directorio también se denominan entradas de directorio o “dentries“.

Cada inodo tiene un número de inodo, que es único dentro de un sistema de archivos. El mismo número de inodo puede aparecer en más de un sistema de archivos. Sin embargo, el ID del sistema de archivos y el número de inodo se combinan para crear un identificador único. Esto independientemente de cuántos sistemas de archivos estén montados en tu sistema Linux.

Recuerda, en Linux, no montas un disco duro o una partición. Montas el sistema de archivos que está en la partición, por lo que es fácil tener múltiples sistemas de archivos sin darte cuenta. Si tienes múltiples discos duros o particiones en una sola unidad, tienes más de un sistema de archivos. Pueden ser del mismo tipo, todos ext4, por ejemplo, pero seguirán siendo sistemas de archivos distintos.

Todos los inodes se mantienen en una tabla. Utilizando un número de inodo, el sistema de archivos calcula fácilmente el desplazamiento en la tabla de inodo en la que se encuentra ese inodo. Puedes ver por qué la “i” en inodo significa índice.

La variable que contiene el número de inodo se declara en el código fuente como un entero largo sin signo de 32 bits. Esto significa que el número de inodo es un valor entero con un tamaño máximo de 2^32, que se calcula en 4,294,967,295. Un poco más de 4 mil millones de inodos.

Máximo teórico

Ese es el máximo teórico. En la práctica, el número de inodos en un sistema de archivos ext4 se determina de manera diferente. Se hace cuando el sistema de archivos crea en una relación predeterminada de un inodo por 16 KB de capacidad del sistema de archivos. Las estructuras de directorio se crean sobre la marcha cuando el sistema de archivos está en uso. Esto debido a que los archivos y directorios se crean dentro del sistema de archivos.

Hay un comando que puedes usar para ver cuántos inodos hay en un sistema de archivos en tu computadora. La opción –i (inodos) del comando df le indica que muestre su salida en números de inodos.

Vamos a ver el sistema de archivos en la primera partición en el primer disco duro, así que escribimos lo siguiente:

La salida nos muestra lo siguiente:

  • File System: el sistema de archivos sobre el que se informa.
  • Inodes: el número total de inodos en este sistema de archivos.
  • IUsed: la cantidad de inodos en uso.
  • IFree: el número de inodos restantes disponibles para su uso.
  • IUse%: El porcentaje de inodos usados.
  • Mounted on: el punto de montaje para este sistema de archivos.

Hemos utilizado el 10 por ciento de los inodos en este sistema de archivos. Los archivos se almacenan en el disco duro en bloques de disco. Cada inodo apunta a los bloques de disco que almacenan el contenido del archivo que representan. Si tienes millones de archivos pequeños, puedes quedarte sin inodos antes de quedarte sin espacio en el disco duro. Sin embargo, es un problema muy difícil de encontrar.

Problema antiguo

En el pasado, algunos servidores de correo que almacenaban mensajes de correo electrónico como archivos discretos (que rápidamente llevaron a grandes colecciones de archivos pequeños) tenían este problema. Sin embargo, cuando esas aplicaciones cambiaron sus back-end a bases de datos, esto resolvió el problema. El sistema doméstico promedio no se quedará sin inodos. Esto es genial porque, con el sistema de archivos ext4, no puedes agregar más inodos sin reinstalar el sistema de archivos.

Para ver el tamaño de los bloques de disco en tu sistema de archivos, puedes usar el comando blockdev con la opción –getbsz (obtener tamaño de bloque):

El tamaño del bloque es de 4096 bytes.

Usemos la opción –B (tamaño de bloque) para especificar un tamaño de bloque de 4096 bytes y verifiquemos el uso regular del disco:

Esta salida nos muestra:

  • File System: el sistema de archivos sobre el que queremos información.
  • 4K-blocks: el número total de bloques de 4 KB en este sistema de archivos.
  • Used: cuántos bloques 4K están en uso.
  • Available: el número de bloques restantes de 4 KB disponibles para su uso.
  • Use%: el porcentaje de bloques de 4 KB que se han utilizado.
  • Mounted on: el punto de montaje para este sistema de archivos.

En nuestro ejemplo, el almacenamiento de archivos (y el almacenamiento de los inodes y las estructuras de directorio) ha utilizado el 28 por ciento del espacio en este sistema de archivos, a un costo del 10 por ciento de los inodos, por lo que estamos en buena forma.

Metadatos de inodo

Para ver el número de inodo de un archivo, podemos usar ls con la opción –i (inodo):

El número de inodo para este archivo es 1441801, por lo que este inodo contiene los metadatos para este archivo. Asimismo, los punteros a los bloques de disco donde reside el archivo en el disco duro. Si el archivo está fragmentado, es muy grande o ambos, algunos de los bloques a los que apunta el inodo podrían contener más punteros a otros bloques de disco. Y algunos de esos otros bloques de disco también pueden contener punteros a otro conjunto de bloques de disco. Esto supera el problema de que el inodo tiene un tamaño fijo. Esto es capaz de contener un número finito de punteros en los bloques de disco.

Ese método fue reemplazado por un nuevo esquema que utiliza “extensiones”. Estas registran el bloque inicial y final de cada conjunto de bloques contiguos utilizados para almacenar el archivo. Si el archivo no está fragmentado, solo tiene que almacenar el primer bloque y la longitud del archivo. Si el archivo está fragmentado, debe almacenar el primer y el último bloque de cada parte del archivo. Este método es (obviamente) más eficiente.

Si deseas ver si tu sistema de archivos utiliza punteros o extensiones de bloque de disco, puedes ver dentro de un inodo. Para hacerlo, utilizaremos el  comando debugfs con la –R opción (solicitud) y le pasaremos el inodo del archivo de interés. Esto le pide a debugfs que use su comando interno “stat” para mostrar el contenido del inodo. Los números de inodo solo son únicos dentro de un sistema de archivos. Por ello también debemos decirle a debugfs el sistema de archivos en el que reside el inodo.

Ejemplo

Así es como se vería este comando de ejemplo:

Como se muestra a continuación, el comando debugfs extrae la información del inodo y nos la presenta en less:

Se nos muestra la siguiente información:

  • Inode: El número del inodo que estamos viendo.
  • Type: Este es un archivo normal, no un directorio o enlace simbólico.
  • Mode: los permisos de archivo en octal.
  • Flags: Indicadores que representan diferentes características o funcionalidades. El 0x80000 es el indicador de “extensión” (más sobre esto a continuación).
  • Generation: un sistema de archivos de red (NFS) utiliza esto cuando alguien accede a sistemas de archivos remotos a través de una conexión de red. Esto para simular como si estuvieran montados en la máquina local. Los números de inodo y generación se utilizan como una forma de identificador de archivo.
  • Version: la versión del inodo.
  • User el propietario del archivo.
  • Group: el propietario del grupo del archivo.
  • Project: siempre debe ser cero.
  • Size: el tamaño del archivo.
  • File ACL: la lista de control de acceso a archivos. Estos fueron diseñados para permitirte dar acceso controlado a personas que no están en el grupo de propietarios.
  • Links: la cantidad de enlaces duros al archivo.
  • Blockcount: la cantidad de espacio en el disco duro asignado a este archivo, dado en fragmentos de 512 bytes. A nuestro archivo se le han asignado ocho de estos, que son 4.096 bytes. Por lo tanto, nuestro archivo de 98 bytes se encuentra dentro de un solo bloque de disco de 4.096 bytes.
  • Fragment: este archivo no está fragmentado. (Este es un indicador obsoleto).
  • Ctime: la hora a la que se creó el archivo.
  • Atime: la hora a la que se accedió por última vez a este archivo.
  • Mtime:

La hora a la que se modificó este archivo por última vez.

  • Crtime: la hora a la que se creó el archivo.
  • Size of extra inode fields: el sistema de archivos ext4 introdujo la capacidad de asignar un inodo en disco más grande en el momento del formato. Este valor es el número de bytes adicionales que usa el inodo. Este espacio adicional también se puede utilizar para acomodar requisitos futuros para nuevos núcleos o para almacenar atributos extendidos.
  • Inode checksum: una suma de comprobación para este inodo, que permite detectar si el inodo está dañado.
  • Extents: si se usan extensiones (en ext4, son, por defecto), los metadatos con respecto al uso del bloque de disco de los archivos tienen dos números. Estos indican los bloques de inicio y fin de cada parte de un archivo fragmentado. Esto es más eficiente que almacenar cada bloque de disco ocupado por cada parte de un archivo. Tenemos una extensión porque nuestro archivo pequeño se encuentra en un bloque de disco en este desplazamiento de bloque.

¿Dónde está el nombre del archivo?

Ahora tenemos mucha información sobre el archivo, pero, como habrás notado, no obtuvimos el nombre del archivo. Aquí es donde entra en juego la estructura de directorios.

En Linux, al igual que un archivo, un directorio tiene un inodo. Sin embargo, este no apunta a los bloques de disco que contienen datos de archivo. Un inodo de directorio apunta a bloques de disco que contienen estructuras de directorio.

En comparación con un inodo, una estructura de directorio contiene una cantidad limitada de información sobre un archivo. Solo contiene el número de inodo del archivo, el nombre y la longitud del nombre.

El inodo y la estructura del directorio contienen todo lo que tú (o una aplicación) necesita saber sobre un archivo o directorio. La estructura del directorio está en un bloque de disco del directorio, por lo que sabemos el directorio en el que se encuentra el archivo. La estructura del directorio nos da el nombre del archivo y el número de inodo. El inodo nos dice todo lo demás sobre el archivo, incluidas los registros temporales, los permisos y dónde encontrar los datos del archivo en el sistema de archivos.

Inodos de directorio

Puedes ver el número de inodo de un directorio tan fácilmente como puede verlos para los archivos.

En el siguiente ejemplo, usaremos ls con las opciones –l (formato largo), -i (inodo) y –d (directorio), y veremos el directorio work:

Debido a que utilizamos la opción (directorio) –dls informa sobre el directorio en sí, no sobre su contenido. El inodo para este directorio es 1443016.

Para repetir eso para el directorio home, escribimos lo siguiente:

El inodo para el directorio home es 1447510, y el directorio work está en el directorio home. Ahora, veamos el contenido del directorio work. En lugar de la opción -d (directorio), usaremos la opción –a (todos). Esto nos mostrará las entradas de directorio que generalmente están ocultas.

Escribimos lo siguiente:

Como utilizamos la opción -a (todos), se muestran las entradas de un solo punto (.) Y doble punto (..). Estas entradas representan el directorio en sí (punto único) y su directorio padre (punto doble).

Si observas el número de inodo para la entrada de punto único, significa que es 1443016. Este es el mismo número de inodo que obtuvimos cuando descubrimos el número de inodo para el directorio work. Además, el número de inodo para la entrada de doble punto es el mismo que el número de inodo para el directorio home.

Es por eso que puedes usar el comando cd.. para subir un nivel en el árbol de directorios. Del mismo modo, cuando precede a un nombre de aplicación o script   ./, le permite a la shell saber desde dónde iniciar la aplicación o script.

Inodos y Enlaces

Como hemos cubierto, se requieren tres componentes para tener un archivo bien formado y accesible en el sistema de archivos. Estos son: el archivo, la estructura del directorio y el inodo. El archivo son los datos almacenados en el disco duro, la estructura del directorio contiene el nombre del archivo y su número de inodo. Por su parte el inodo contiene todos los metadatos del archivo.

Los enlaces simbólicos son entradas del sistema de archivos, parecen archivos, pero en realidad son accesos directos que apuntan a un archivo o directorio existente. Veamos cómo administran esto y cómo se usan los tres elementos para lograrlo.

Digamos que tenemos un directorio con dos archivos: uno es un script y el otro es una aplicación, como se muestra a continuación:

Podemos usar el comando ln y la opción –s (simbólica) para crear un enlace suave al archivo de script, así:

Hemos creado un enlace a my_script.sh llamado geek.sh. Podemos escribir lo siguiente y usar ls para ver los dos archivos de script:

La entrada para geek.sh aparece en azul. El primer carácter de los indicadores de permisos es una “l” para el enlace, y el  ->  apunta a my_script.sh. Todo esto indica que geek.sh es un enlace.

Como probablemente esperas, los dos archivos de script tienen números de inodo diferentes. Sin embargo, lo que es más sorprendente es el enlace suave geek.sh, no tiene los mismos permisos de usuario que el archivo de script original. De hecho, los permisos para geek.sh son mucho más liberales: todos los usuarios tienen permisos completos.

Estructura

La estructura del directorio geek.sh contiene el nombre del enlace y su inodo. Cuando intentas utilizar el enlace, se hace referencia a su inodo, al igual que un archivo normal. El inodo del enlace apuntará a un bloque de disco, pero en lugar de contener datos del contenido del archivo, el bloque de disco contiene el nombre del archivo original. El sistema de archivos redirige al archivo original.

Eliminaremos el archivo original y veremos qué sucede cuando escribimos lo siguiente para ver el contenido de geek.sh:

El enlace simbólico se rompe y la redirección falla.

Ahora escribimos lo siguiente para crear un enlace duro al archivo de la aplicación:

Para ver los inodos de estos dos archivos, escribimos lo siguiente:

Ambos parecen archivos normales. Nada sobre geek-app indica que es un enlace en la forma en que ls hizo que se listara geek.sh. Además, geek-app tiene los mismos permisos de usuario que el archivo original. Sin embargo, lo que podría sorprender es que ambas aplicaciones tienen el mismo número de inodo: 1441797.

La entrada del directorio para geek-app contiene el nombre “geek-app” y un número de inodo, pero es el mismo que el número de inodo del archivo original. Entonces, tenemos dos entradas del sistema de archivos con nombres diferentes que apuntan al mismo inodo. De hecho, cualquier número de elementos puede apuntar al mismo inodo.

Escribiremos lo siguiente y utilizaremos el programa stat para ver el archivo de destino:

Vemos que dos enlaces duros apuntan a este archivo. Esto se almacena en el inodo.

En el siguiente ejemplo, eliminamos el archivo original e intentamos usar el enlace con una contraseña secreta y segura:

Resultado

Sorprendentemente, la aplicación se ejecuta como se esperaba, pero ¿cómo? Funciona porque, cuando eliminas un archivo, el inodo es libre de ser reutilizado. La estructura del directorio está marcada como que tiene un número de inodo cero. Por otra parte, los bloques de disco están disponibles para que otro archivo se almacene en ese espacio.

Sin embargo, si el número de enlaces duros al inodo es mayor que uno, el recuento de enlaces duros se reduce en uno. Asimismo, el número de inodo de la estructura de directorios del archivo eliminado se establece en cero. El contenido del archivo en el disco duro y el inodo todavía están disponibles para los enlaces duros existentes.

Escribiremos lo siguiente y utilizaremos stat una vez más, esta vez en geek-app:

Estos detalles se extraen del mismo inodo (1441797) así como en el comando stat anterior. El recuento de enlaces se redujo en uno.

Debido a que tenemos un enlace rígido a este inodo, si eliminamos geek-app, realmente eliminaríamos el archivo. El sistema de archivos liberará el inodo y marcará la estructura del directorio con un inodo de cero. Un archivo nuevo puede sobrescribir el almacenamiento de datos en el disco duro.

Generalidades de los inodos

Es un sistema ordenado, pero tiene implicaciones. Para leer un archivo, el sistema de archivos tiene que hacer todo lo siguiente:

  • Encontrar la estructura de directorio correcta.
  • Leer el número de inodo.
  • Encontrar el inodo correcto.
  • Leer la información del inodo.
  • Seguir los enlaces de inodo o las extensiones a los bloques de disco relevantes.
  • Leer los datos del archivo

Es necesario saltar un poco más si los datos no son contiguos.

Imagina el trabajo que debe realizarse para que ls haga una lista de archivos de formato largo de muchos archivos. Hay mucho de ida y vuelta solo para que ls logre obtener la información que necesita para generar su salida.

Por supuesto, acelerar el acceso al sistema de archivos es la razón por la cual Linux intenta hacer el almacenamiento en caché de archivos preventivos. Esto ayuda mucho, pero a veces, como con cualquier sistema de archivos, las implicaciones generales pueden ser evidentes.