Cerramos el módulo 3 con una constatación incómoda: llevábamos tres módulos escribiendo /var/lib/meteora/lecturas/2026-08-31.dat como si esa cadena de texto fuera algo evidente, cuando en el módulo 2 dejamos el almacenamiento en un punto muy distinto. Allí, un SSD NVMe era un vector de bloques numerados de 0 a N, direccionables por LBA, sin nombres, sin carpetas, sin tamaños y sin dueños. Un array gigantesco de 512 o 4.096 bytes por casilla. Nada más.
Entre ese vector de bloques y la ruta /var/lib/meteora/lecturas/2026-08-31.dat hay una de las abstracciones más logradas de la informática: el sistema de archivos. Es la pieza que convierte "el bloque 8.394.271" en "el fichero de lecturas de ayer", que recuerda quién lo creó y cuándo, que sabe que ocupa 17 MB repartidos en miles de bloques dispersos, y que consigue que un programa en C pueda leerlo sin saber absolutamente nada de LBA, sectores ni geometría.
Esta lección construye esa abstracción desde abajo. Vamos a definir qué es un fichero con precisión, ver qué metadatos lleva y dónde viven, diseccionar el inodo —la estructura central de todo sistema UNIX—, recorrer la disposición física de un sistema de archivos sobre el dispositivo, calcular por qué el tamaño de bloque es un compromiso y no una casualidad, y terminar comparando las familias de sistemas de archivos que existen para decidir, con argumentos, cuál merece /var/lib/meteora.
Contenido
- Del bloque crudo al fichero: qué problema resuelve la abstracción
- Qué es un fichero: contenido, metadatos y nombre
- Los siete tipos de fichero de UNIX
ls -lystatinterpretados campo a campo- El inodo: qué contiene y qué no contiene
- Números de inodo,
ls -iy el agotamiento condf -i - Disposición física de un sistema de archivos en el dispositivo
- El tamaño de bloque y su compromiso, calculado
- Marcas de tiempo:
atime,mtime,ctime,crtimey el porqué denoatime - Familias de sistemas de archivos comparadas
- La decisión de Meteora para
/var/lib/meteora
Del bloque crudo al fichero: qué problema resuelve la abstracción
Imagina por un momento que Meteora no tuviera sistema de archivos y trabajara directamente sobre /dev/nvme0n1, el dispositivo de bloques del módulo 2. El ingestor tendría que resolver, él solito, esta lista de problemas:
| Problema | Qué tendría que hacer el ingestor sin sistema de archivos |
|---|---|
| Ubicación | Recordar en qué LBA empieza el día de hoy, y almacenarlo en algún sitio... ¿dónde? |
| Crecimiento | Saber cuántos bloques reservar por adelantado, porque no puede "crecer" sobre un vecino |
| Espacio libre | Llevar su propia contabilidad de qué bloques están usados y cuáles no |
| Nombres | Inventar un índice propio que traduzca "31 de agosto" a un número de bloque |
| Concurrencia | Coordinarse con el agregador y con meteo-api para no pisarse bloques |
| Permisos | No hay: cualquiera con acceso al dispositivo lee y escribe todo |
| Persistencia de la contabilidad | Si se corta la luz mientras actualiza su índice, lo pierde todo |
Cada programa del servidor tendría que resolver los siete, cada uno a su manera, y ninguno podría cooperar con los demás. Es exactamente la situación que describimos en 01-01 al hablar del sistema operativo como máquina extendida: sin él, cada aplicación reimplementa el hardware.
El sistema de archivos resuelve los siete de golpe con una sola idea:
Un fichero es una secuencia de bytes con nombre, tamaño y propietario, que el sistema almacena donde quiere y el programa lee como si fuera continua.
Las cuatro palabras clave de esa definición merecen atención:
- Secuencia de bytes. En UNIX un fichero no tiene estructura interna conocida por el sistema. No hay "registros", ni "campos", ni tipos. Que
2026-08-31.datcontenga 720.000 estructurasLecturade 24 bytes es un acuerdo entre los programas de Meteora, invisible para el núcleo. Otros sistemas históricos (los de IBM, VMS) sí imponían estructura de registros, y la industria acabó dándole la razón al modelo plano de UNIX por su simplicidad. - Con nombre. El nombre es el asa por la que el usuario agarra el fichero. Veremos en el apartado 5 la sorpresa: el nombre no está dentro del fichero.
- Donde quiere. El sistema decide qué bloques usa. Eso es lo que estudiaremos en Asignación de Espacio, Journaling e Integridad.
- Como si fuera continua. Esta es la magia.
2026-08-31.datocupa 4.219 bloques que pueden estar desperdigados por todo el SSD, y sin embargoread()los entrega en orden como un chorro de bytes. Es la misma clase de ilusión que la memoria virtual del módulo 2: direcciones lógicas contiguas sobre almacenamiento físico disperso.
De hecho, el paralelismo con la memoria virtual es tan exacto que conviene fijarlo, porque te ahorrará esfuerzo en todo el módulo:
| Memoria virtual (02-04) | Sistema de archivos (módulo 4) |
|---|---|
| Espacio de direcciones virtual del proceso | El fichero como secuencia de bytes 0..N |
| Página (4 KiB) | Bloque lógico (4 KiB) |
| Marco de página en RAM | Bloque físico en el dispositivo |
| Tabla de páginas | Punteros/extents del inodo |
| MMU traduce virtual → físico | El sistema de archivos traduce desplazamiento → LBA |
| Fallo de página trae la página de disco | read() trae el bloque a la caché de páginas |
Es la misma idea aplicada dos veces: una tabla de traducción que convierte un espacio lógico ordenado en un espacio físico desordenado.
Qué es un fichero: contenido, metadatos y nombre
Un fichero tiene tres partes, y viven en tres sitios distintos. Esta separación es la clave de todo lo demás:
graph LR
subgraph DIR["Directorio (04-02)"]
N["nombre: 2026-08-31.dat<br/>inodo: 1180934"]
end
subgraph INO["Inodo nº 1180934"]
M["tipo, permisos, dueño,<br/>tamaño, fechas, punteros"]
end
subgraph DAT["Zona de datos"]
D["4.219 bloques<br/>con los 17.280.000 bytes"]
end
N -->|apunta a| M
M -->|apunta a| D
- El contenido: los bytes en sí, en la zona de datos del dispositivo.
- Los metadatos: todo lo que el sistema sabe sobre el fichero. Viven en el inodo.
- El nombre: vive en el directorio que lo contiene, no en el fichero. Lo desarrollaremos en Estructuras de Directorios, pero necesitas saberlo ya para entender el inodo.
Los metadatos típicos de un fichero, con lo que significa cada uno:
| Metadato | Qué es | Ejemplo en Meteora |
|---|---|---|
| Tipo | Regular, directorio, enlace simbólico... | Regular |
| Tamaño | Bytes de contenido | 17.280.000 |
| Bloques | Bloques de 512 B realmente ocupados | 33.760 |
| Propietario (UID) | Usuario dueño | meteora (UID 990) |
| Grupo (GID) | Grupo dueño | meteora (GID 990) |
| Permisos | 12 bits de modo | 0640 |
| Contador de enlaces | Cuántos nombres apuntan a este inodo | 1 |
| Marcas de tiempo | Acceso, modificación, cambio, creación | ver apartado 9 |
| Punteros a datos | Dónde están los bloques | extents (04-05) |
Fíjate en algo que ya se intuye: el nombre no aparece en esa lista. No es un olvido; es la decisión de diseño central de UNIX, y de ella salen los enlaces duros, el borrado diferido y media docena de comportamientos que sorprenden hasta que entiendes esto.
Los siete tipos de fichero de UNIX
En UNIX, la frase "todo es un fichero" se toma en serio. La misma interfaz —open, read, write, close— sirve para un fichero de datos, un teclado, una tubería o una conexión de red. Lo que cambia es el tipo, un campo de 4 bits en el inodo:
Símbolo en ls -l |
Tipo | Qué es | Ejemplo de Meteora |
|---|---|---|---|
- |
Regular | Secuencia de bytes en el disco | /var/lib/meteora/lecturas/2026-08-31.dat |
d |
Directorio | Tabla de pares (nombre, inodo) | /var/lib/meteora/lecturas/ |
l |
Enlace simbólico | Fichero que contiene una ruta | /var/lib/meteora/lecturas/hoy.dat |
b |
Dispositivo de bloque | Acceso por bloques, con caché | /dev/nvme0n1, /dev/md0 |
c |
Dispositivo de carácter | Acceso por bytes, sin caché | /dev/null, /dev/random, /dev/tty |
p |
FIFO (tubería con nombre) | Canal en el sistema de archivos | /run/meteora/lecturas.fifo |
s |
Socket | Punto de comunicación local | /run/meteora/api.sock |
Los tres últimos son viejos conocidos del módulo 3: la FIFO de /run/meteora/lecturas.fifo la usamos en Comunicación entre Procesos, y los sockets de dominio UNIX también. La diferencia es que allí los vimos como mecanismos de IPC y aquí los vemos como entradas del sistema de archivos: tienen inodo, permisos y nombre, pero su contenido no está en el disco —una FIFO tiene un búfer en memoria del núcleo, un socket tiene una cola de red—. Ocupan un inodo y cero bloques de datos.
Lo mismo pasa con los dispositivos de bloque y carácter, que vimos en Gestión de Dispositivos: su inodo no guarda punteros a datos, guarda el par (número mayor, número menor) que identifica al controlador. Un fichero de dispositivo es, literalmente, un inodo con un par de enteros dentro.
ls -l y stat interpretados campo a campo
Vamos a mirarlo de verdad. Este es el listado del directorio de Meteora en meteo-01:
$ ls -l /var/lib/meteora/lecturas/ /dev/nvme0n1 /dev/null /run/meteora/ -rw-r----- 1 meteora meteora 17280000 ago 31 23:59 2026-08-31.dat -rw-r----- 1 meteora meteora 17280000 sep 1 12:40 2026-09-01.dat lrwxrwxrwx 1 meteora meteora 14 sep 1 00:00 hoy.dat -> 2026-09-01.dat drwxr-x--- 2 meteora meteora 4096 sep 1 00:00 archivo brw-rw---- 1 root disk 259, 0 sep 1 08:12 /dev/nvme0n1 crw-rw-rw- 1 root root 1, 3 sep 1 08:12 /dev/null prw-r----- 1 meteora meteora 0 sep 1 08:13 /run/meteora/lecturas.fifo srwxr-xr-x 1 meteora meteora 0 sep 1 08:13 /run/meteora/api.sock
Los campos, de izquierda a derecha:
- Primer carácter: el tipo de la tabla anterior.
-,l,d,b,c,p,s. De un vistazo ya sabes qué es cada cosa. - Nueve caracteres siguientes: los permisos, que veremos en Seguridad y Permisos de Archivos.
- El número tras los permisos: el contador de enlaces. Vale 1 en los ficheros normales y 2 en el directorio
archivo(lo explica 04-02). - Usuario y grupo propietarios:
meteora meteora. - Tamaño: 17.280.000 bytes para las lecturas. Pero mira
/dev/nvme0n1: donde debería estar el tamaño pone259, 0. Son el mayor y el menor. Un fichero de dispositivo no tiene tamaño porque no tiene contenido; en su lugarlsmuestra la pareja que identifica al controlador. Y la FIFO y el socket ponen0, por la misma razón. - Fecha: por defecto el
mtime, no el de creación ni el de último acceso (apartado 9). - Nombre, con el
-> destinoen el enlace simbólico.
ls -l es un resumen. Para verlo todo se usa stat:
$ stat /var/lib/meteora/lecturas/2026-08-31.dat Fichero: /var/lib/meteora/lecturas/2026-08-31.dat Tamaño: 17280000 Bloques: 33760 Bloque E/S: 4096 fichero regular Dispositivo: 9,0 Nodo-i: 1180934 Enlaces: 1 Acceso: (0640/-rw-r-----) Uid: ( 990/meteora) Gid: ( 990/meteora) Acceso: 2026-09-01 06:00:11.482913711 +0200 Modificación:2026-08-31 23:59:58.117204339 +0200 Cambio: 2026-08-31 23:59:58.117204339 +0200 Creación: 2026-08-31 00:00:00.004118220 +0200
Campo a campo, con lo que hay que entender de cada uno:
- Tamaño: 17280000. Bytes lógicos del fichero: exactamente 720.000 lecturas × 24 bytes. Es el número que devuelve
lseek(fd, 0, SEEK_END). - Bloques: 33760. Aquí hay una trampa clásica:
statcuenta bloques de 512 bytes, siempre, independientemente del tamaño de bloque real del sistema de archivos. 33.760 × 512 = 17.285.120 bytes ocupados en disco, algo más que los 17.280.000 lógicos. La diferencia son 5.120 bytes: 4 KiB del último bloque parcialmente usado más los metadatos del árbol de extents. Que "bloques × 512" sea menor que el tamaño es la firma de un fichero disperso (lo veremos en 04-04). - Bloque E/S: 4096. El tamaño de bloque preferido para las lecturas; leer en múltiplos de este número evita trabajo extra al núcleo.
- Dispositivo: 9,0. Mayor 9, menor 0:
/dev/md0, el RAID 1 que montamos en 02-05. Este par identifica en qué sistema de archivos vive el inodo, y la pareja (dispositivo, nodo-i) es lo único que identifica un fichero de forma única en toda la máquina. - Nodo-i: 1180934. El número de inodo. El apartado 6 se dedica a él.
- Enlaces: 1. Un solo nombre apunta a este inodo (04-02).
- Acceso (0640). Doce bits de modo, mostrados en octal y en simbólico (04-06).
- Uid/Gid 990. El usuario y el grupo
meteora. Ojo: el inodo guarda números, no nombres; la traducción ameteorala hacestatconsultando/etc/passwd. - Las cuatro fechas: apartado 9.
El inodo: qué contiene y qué no contiene
El inodo (index node) es la estructura de datos que es el fichero. Todo lo demás son referencias a él. Vive en el disco, en una zona reservada, y tiene un tamaño fijo: 256 bytes en un ext4 moderno (128 en los antiguos, configurable al formatear).
Su contenido, agrupado:
| Grupo | Campos | Bytes aprox. |
|---|---|---|
| Identidad | Tipo (4 bits) + permisos (12 bits), UID, GID | 8 |
| Tamaño | Tamaño lógico en bytes (64 bits), bloques ocupados | 12 |
| Enlaces | Contador de nombres que lo referencian | 2 |
| Tiempos | atime, mtime, ctime, dtime, crtime (con nanosegundos) | 40 |
| Datos | 60 bytes de punteros/extents (04-05) | 60 |
| Extras | Banderas (chattr), versión, checksum, atributos extendidos |
resto |
Y ahora lo importante, que es lo que no está:
El nombre del fichero no está en el inodo. Tampoco está la ruta, ni el directorio al que pertenece, ni nada que lo relacione con
/var/lib/meteora/lecturas/2026-08-31.dat.
El inodo 1180934 no sabe cómo se llama. Sabe que es un fichero regular de 17.280.000 bytes que pertenece al UID 990, que hay 1 nombre en algún sitio apuntando a él, y en qué bloques están sus datos. Nada más.
Esto no es una limitación: es la decisión de diseño de la que cuelga medio módulo. Sus consecuencias, que iremos desplegando:
| Consecuencia | Dónde se explica |
|---|---|
| Un mismo fichero puede tener varios nombres (enlaces duros) | 04-02 |
| Renombrar es instantáneo: solo cambia una entrada de directorio | 04-02 |
Borrar es unlink: quitar un nombre, no destruir el fichero |
04-02 |
| Un fichero abierto sin ningún nombre sigue existiendo | 04-02, 04-04 |
| El nombre no tiene permisos; los permisos están en el inodo | 04-06 |
Un fichero en uso puede sustituirse atómicamente con rename() |
04-04 |
Guarda esta frase: el inodo es el fichero; el nombre es solo una etiqueta pegada desde fuera.
Números de inodo, ls -i y el agotamiento con df -i
Cada inodo tiene un número único dentro de su sistema de archivos. Se ve con ls -i:
Dos ficheros del mismo sistema de archivos con el mismo número de inodo son el mismo fichero. Dos ficheros de sistemas de archivos distintos pueden compartir número sin tener nada que ver: por eso la identidad real es el par (dispositivo, inodo), st_dev + st_ino en stat. Es exactamente lo que comprueba find -samefile y lo que usa rsync para no copiar dos veces el mismo contenido enlazado.
Ahora lo práctico. En ext4, el número de inodos se fija al formatear y no se puede aumentar después. Se reservan por adelantado, con una relación por defecto de un inodo por cada 16 KiB de capacidad:
$ df -h /var/lib/meteora S.ficheros Tamaño Usados Disp Uso% Montado en /dev/md0 196G 41G 146G 22% /var/lib/meteora $ df -i /var/lib/meteora S.ficheros Nodos-i NUsados NLibres NUso% Montado en /dev/md0 13107200 1834 13105366 1% /var/lib/meteora
Interpretación: el volumen tiene 13.107.200 inodos (200 GiB ÷ 16 KiB) y solo usa 1.834, porque Meteora guarda un fichero grande por día y lleva unos cinco años funcionando. Con esa política, en 100 años usaría 36.500 inodos: el 0,28 %.
Al revés, sin embargo, ocurre el fallo más desconcertante de la administración de sistemas:
$ df -h /var/spool/cache S.ficheros Tamaño Usados Disp Uso% Montado en /dev/sdb1 50G 12G 36G 26% /var/spool/cache ← ¡74 % libre! $ df -i /var/spool/cache S.ficheros Nodos-i NUsados NLibres NUso% Montado en /dev/sdb1 3276800 3276800 0 100% /var/spool/cache ← 0 libres $ touch /var/spool/cache/prueba touch: no se puede efectuar `touch' sobre 'prueba': No queda espacio en el dispositivo
"No queda espacio en el dispositivo" con 36 GB libres. El error es ENOSPC y es literal desde el punto de vista del núcleo: no queda espacio de inodos. Un proceso que crea millones de ficheros diminutos —cachés, sesiones, colas de correo— agota la reserva de inodos mucho antes que los bloques. Regla de diagnóstico: ante un ENOSPC, ejecuta siempre df -h y df -i; si la primera no explica nada, la segunda lo hará.
Para localizar al culpable:
$ sudo find /var/spool/cache -xdev -type f -printf '%h\n' | sort | uniq -c | sort -rn | head -5 2984112 /var/spool/cache/sesiones 12043 /var/spool/cache/tmp
El comando cuenta ficheros por directorio: -xdev evita saltar a otros sistemas de archivos, -printf '%h\n' imprime el directorio de cada fichero, y sort | uniq -c | sort -rn agrupa y ordena. Casi tres millones de ficheros en sesiones: ahí está el problema.
La solución no es agrandar el disco, porque los inodos no crecen: hay que borrar ficheros o reformatear con mkfs.ext4 -i 4096 (un inodo cada 4 KiB, cuatro veces más) o -N 8000000 (número explícito). Este es uno de los argumentos a favor de XFS y Btrfs, que asignan inodos dinámicamente y no sufren este problema.
Disposición física de un sistema de archivos en el dispositivo
Ya sabemos qué es un inodo. ¿Dónde está físicamente? Vamos a abrir el dispositivo por dentro. La jerarquía de unidades, de menor a mayor:
| Unidad | Tamaño típico | Quién la define |
|---|---|---|
| Sector | 512 B (lógico) / 4.096 B (físico) | El hardware del disco |
| Bloque lógico | 1, 2 o 4 KiB | El sistema de archivos, al formatear |
| Grupo de bloques | 128 MiB en ext4 | El sistema de archivos |
| Sistema de archivos | La partición entera | El administrador |
El sector es la unidad mínima que el dispositivo sabe leer o escribir; lo vimos en 02-05. El bloque lógico es la unidad mínima que el sistema de archivos sabe asignar: aunque el disco pueda leer 512 bytes, ext4 nunca asigna menos de un bloque a un fichero.
Un ext4 se divide en grupos de bloques de 128 MiB, cada uno con su propia contabilidad. La razón es de rendimiento y viene directa del módulo 2: mantener juntos los metadatos y los datos que se usan juntos reduce los desplazamientos del cabezal en un HDD y mejora la localidad en un SSD.
graph TB
subgraph FS["/dev/md0 — ext4 de 200 GiB, 1.600 grupos de 128 MiB"]
BOOT["Bloque 0<br/>1 KiB de arranque"]
subgraph G0["Grupo de bloques 0"]
SB["Superbloque<br/>(1 bloque)"]
GD["Descriptores de grupo<br/>(N bloques)"]
BB["Mapa de bits<br/>de BLOQUES<br/>(1 bloque)"]
IB["Mapa de bits<br/>de INODOS<br/>(1 bloque)"]
IT["Tabla de inodos<br/>(512 bloques)"]
DZ["ZONA DE DATOS<br/>(~31.000 bloques)"]
end
G1["Grupo 1<br/>(igual estructura)"]
GN["... Grupo 1.599"]
end
BOOT --> SB --> GD --> BB --> IB --> IT --> DZ --> G1 --> GN
Pieza por pieza:
El superbloque. Es la ficha de identidad del sistema de archivos, y ocupa un solo bloque. Contiene el número total de inodos y de bloques, cuántos quedan libres, el tamaño de bloque, el tamaño del inodo, el número de bloques por grupo, el UUID, la etiqueta, la fecha del último montaje, el contador de montajes y el estado (limpio o sucio, que será decisivo en 04-05). Sin superbloque no se puede montar nada, porque no se sabe ni dónde empiezan los inodos. Por eso ext4 guarda copias de seguridad en varios grupos:
$ sudo dumpe2fs /dev/md0 | grep -i superblock Primary superblock at 0, Group descriptors at 1-13 Backup superblock at 32768, Group descriptors at 32769-32781 Backup superblock at 98304, Group descriptors at 98305-98317 Backup superblock at 163840, ...
Si el primario se corrompe, se recupera con sudo e2fsck -b 32768 /dev/md0, que le dice a e2fsck que use el respaldo del bloque 32768. Es un comando que conviene tener anotado: salva volúmenes que parecían perdidos.
Los descriptores de grupo. Un array con una entrada por grupo, que dice dónde están los mapas de bits y la tabla de inodos de ese grupo y cuántos elementos libres tiene. Es el índice que permite encontrar todo lo demás.
El mapa de bits de bloques. Un bit por bloque del grupo: 1 = ocupado, 0 = libre. Con bloques de 4 KiB, un grupo de 128 MiB tiene 32.768 bloques, que son 32.768 bits = 4.096 bytes: exactamente un bloque. No es casualidad; el tamaño del grupo se elige precisamente para que su mapa de bits quepa en un bloque.
El mapa de bits de inodos. Lo mismo para los inodos del grupo.
La tabla de inodos. El array de inodos propiamente dicho. Si un grupo tiene 8.192 inodos de 256 bytes, ocupa 2 MiB = 512 bloques. Aquí es donde se calcula la posición de un inodo a partir de su número, con aritmética pura y sin buscar en ningún índice:
/* Localizar el inodo 1180934 en un ext4 con 8.192 inodos por grupo */
unsigned grupo = (1180934 - 1) / 8192; /* = 144 → grupo 144 */
unsigned indice = (1180934 - 1) % 8192; /* = 1157 → posición 1157 */
off_t posicion = inicio_tabla_inodos[144] + (off_t)1157 * 256;Dos divisiones y una multiplicación: eso es todo lo que cuesta pasar de un número de inodo a su posición en el disco. Los inodos se numeran desde 1, de ahí el - 1. Esta es la razón profunda de que el inodo sea un número y no un nombre: buscar un nombre exigiría recorrer una tabla; un número se resuelve con aritmética en nanosegundos.
La zona de datos. Todo lo demás: los bloques donde están los bytes de los ficheros.
Puedes verlo en tu máquina con dumpe2fs:
$ sudo dumpe2fs -h /dev/md0 | head -20 Filesystem volume name: meteora-datos Filesystem UUID: 9f3a1c22-7d4e-4a51-b7c8-2e5f0a1d6b93 Filesystem features: has_journal ext_attr dir_index extent 64bit Filesystem state: clean Inode count: 13107200 Block count: 52428800 Free blocks: 41156923 First block: 0 Block size: 4096 Blocks per group: 32768 Inodes per group: 8192 Inode size: 256
Cada línea es un campo del superbloque real. Block count: 52428800 × 4.096 = 200 GiB. Filesystem state: clean significa que se desmontó correctamente. Y dir_index y extent son características que aparecerán en 04-02 y 04-05.
El tamaño de bloque y su compromiso, calculado
El tamaño de bloque se elige al formatear y no se puede cambiar después. Es un compromiso genuino, y se ve con números.
El coste de un bloque grande: fragmentación interna. Como la asignación es por bloques enteros, el último bloque de cada fichero queda parcialmente vacío, y ese espacio se pierde. En promedio se desperdicia medio bloque por fichero.
El coste de un bloque pequeño: más bloques que gestionar. Más entradas en los metadatos, más trabajo de asignación, y peticiones de E/S más pequeñas.
Con los ficheros reales de Meteora (17.280.000 bytes):
| Tamaño de bloque | Bloques necesarios | Espacio ocupado | Desperdicio | Mapa de bits para 200 GiB |
|---|---|---|---|---|
| 1 KiB | 16.875 | 17.280.000 B | 0 B (exacto) | 25 MiB |
| 2 KiB | 8.438 | 17.281.024 B | 1.024 B | 12,5 MiB |
| 4 KiB | 4.219 | 17.281.024 B | 1.024 B | 6,25 MiB |
| 16 KiB | 1.055 | 17.285.120 B | 5.120 B | 1,6 MiB |
| 64 KiB | 264 | 17.301.504 B | 21.504 B | 0,4 MiB |
Para ficheros de 17 MB el desperdicio es irrelevante en todos los casos: 21 KB sobre 17 MB es el 0,12 %. Pero el número de bloques a gestionar cambia por un factor de 64.
Ahora el escenario contrario, un directorio con un millón de ficheros de 800 bytes (sesiones, no lecturas):
| Tamaño de bloque | Espacio ocupado por 1.000.000 ficheros | Desperdicio |
|---|---|---|
| 1 KiB | 1.024 MB | 224 MB (22 %) |
| 4 KiB | 4.096 MB | 3.296 MB (80 %) |
| 64 KiB | 65.536 MB | 64.736 MB (99 %) |
Con bloques de 64 KiB, un millón de ficheros de 800 bytes ocuparía 64 GB para almacenar 800 MB. El mismo tamaño de bloque que era irrelevante para las lecturas es catastrófico aquí.
Por qué 4 KiB es el estándar universal, y no es una convención arbitraria:
- Coincide con el tamaño de página (módulo 2). La caché de páginas del núcleo trabaja en páginas de 4 KiB; si el bloque midiera lo mismo, un bloque = una página y no hay que trocear ni juntar nada. Un bloque mayor que la página no se puede mapear con
mmap()de forma directa, que es precisamente lo que hace elagregadorcon2026-08-31.dat(02-04). De hecho, Linux no soporta bloques mayores que el tamaño de página, así que en x86-64 el máximo es 4 KiB. - Coincide con el sector físico de los discos modernos (Advanced Format, 4Kn), así que ninguna escritura provoca el ciclo leer-modificar-escribir.
- Equilibra el desperdicio para la distribución real de tamaños de ficheros en un sistema típico.
Regla práctica: usa 4 KiB salvo que tengas una razón medida para no hacerlo. La razón para bajar a 1 KiB es un volumen dedicado a millones de ficheros minúsculos; para subir tendrías que irse a XFS en arquitecturas con páginas mayores, o a sistemas de archivos con bigalloc.
Marcas de tiempo: atime, mtime, ctime, crtime y el porqué de noatime
Cuatro fechas, y tres de ellas se confunden constantemente:
| Marca | Nombre | Se actualiza cuando... | Se ve con |
|---|---|---|---|
| atime | access time | Se lee el contenido | ls -lu, stat |
| mtime | modify time | Cambia el contenido | ls -l (por defecto) |
| ctime | change time | Cambia el inodo | ls -lc, stat |
| crtime | creation time | Se creó el fichero | stat (ext4, XFS, Btrfs) |
El error más frecuente es creer que ctime es creation time. No lo es: es change time, el momento en que cambió cualquier metadato. Cambiar los permisos con chmod, el dueño con chown o crear un enlace duro modifica el ctime pero no el mtime, porque el contenido no ha cambiado. Y como no se puede alterar hacia atrás (ni siquiera touch -d lo toca), el ctime es la marca que consulta un analista forense: quien manipula un fichero puede falsear atime y mtime, pero al hacerlo actualiza el ctime, delatándose. Volveremos a ello en el módulo 5.
Una tabla de qué toca cada operación sobre 2026-08-31.dat:
| Operación | atime | mtime | ctime |
|---|---|---|---|
cat 2026-08-31.dat |
Sí | No | No |
echo dato >> 2026-08-31.dat |
No | Sí | Sí |
chmod 640 2026-08-31.dat |
No | No | Sí |
chown meteora: 2026-08-31.dat |
No | No | Sí |
mv 2026-08-31.dat viejo.dat |
No | No | No¹ |
ln 2026-08-31.dat copia.dat |
No | No | Sí² |
¹ Renombrar cambia el directorio, no el inodo del fichero. ² Cambia el contador de enlaces, que está en el inodo.
Por qué noatime mejora el rendimiento
Aquí está el problema práctico. Actualizar el atime significa escribir en el disco al leer un fichero. Suena absurdo, y lo es: convierte una operación de solo lectura en una de lectura y escritura.
Los números para Meteora. meteo-api sirve unas 2.000 consultas por hora, cada una leyendo el fichero del día. Con atime estricto, eso son 2.000 escrituras por hora sobre el inodo de un fichero que nadie ha modificado: 48.000 escrituras diarias de metadatos, más su entrada correspondiente en el diario (04-05), sobre un RAID 1 donde cada escritura va a los dos discos. Y sobre un SSD, ciclos de escritura gastados para nada.
Las opciones de montaje disponibles, que aplicaremos en Particiones, Montaje y Sistema de Archivos Virtual:
| Opción | Comportamiento | Coste |
|---|---|---|
strictatime |
Actualiza el atime en cada lectura | Máximo |
relatime |
Solo si el atime es anterior al mtime/ctime, o tiene más de 24 h | Bajo (por defecto desde 2009) |
nodiratime |
Como el anterior, pero sin atime en directorios | Bajo |
noatime |
Nunca actualiza el atime | Cero |
relatime es el compromiso que adoptó Linux: mantiene la semántica que necesitan las herramientas que preguntan "¿se ha leído esto desde la última modificación?" (los clientes de correo, sobre todo) con una fracción del coste. noatime lo elimina del todo.
Meteora monta /var/lib/meteora con noatime, porque ningún programa del sistema consulta el atime de las lecturas y el ahorro es real. La regla general: en un volumen de datos de servidor, noatime es casi siempre correcto; en un volumen de usuarios con clientes de correo antiguos, quédate en relatime.
Familias de sistemas de archivos comparadas
Hay decenas. Estos son los que te vas a encontrar, con lo que de verdad los distingue:
| Sistema | Origen | Estructura | Diario / CoW | Suma de verif. datos | Máx. fichero | Cuándo elegirlo |
|---|---|---|---|---|---|---|
| ext4 | Linux, 2008 | Inodos + extents | Diario | No (solo metadatos) | 16 TiB | Servidor Linux general. La opción segura |
| XFS | SGI, 1994 | Árboles B+ + extents | Diario | No (solo metadatos) | 8 EiB | Ficheros grandes, alto paralelismo, RHEL por defecto |
| Btrfs | Linux, 2009 | Árboles B CoW | Copia al escribir | Sí | 16 EiB | Instantáneas, sumas de verificación, RAID integrado |
| ZFS | Sun, 2005 | Árboles CoW + pools | Copia al escribir | Sí | 16 EiB | Almacenamiento serio. Licencia fuera del núcleo Linux |
| F2FS | Samsung, 2012 | Estructurado en registro | Registro | Opcional | 16 TiB | Memoria flash: móviles, tarjetas SD |
| NTFS | Microsoft, 1993 | MFT + árboles B | Diario | No | 8 PiB | Windows |
| APFS | Apple, 2017 | Árboles CoW | Copia al escribir | Solo metadatos | 8 EiB | macOS, iOS |
| FAT32 | Microsoft, 1996 | Tabla FAT | No | No | 4 GiB | Compatibilidad universal, arranque UEFI |
| exFAT | Microsoft, 2006 | Tabla FAT ampliada | No | No | 128 PiB | Tarjetas SD grandes entre sistemas |
| tmpfs | Linux | Solo en RAM | N/A | N/A | RAM + swap | /run, /dev/shm, ficheros temporales |
| NFS / SMB | Red | Cliente-servidor | Del servidor | Del servidor | Del servidor | Compartir por red (04-03) |
Cuatro observaciones que valen más que la tabla entera:
FAT32 y el límite de 4 GiB. Es el límite real que más gente encuentra en su vida: copiar un vídeo de 5 GB a un pendrive falla, y no por falta de espacio. FAT32 guarda el tamaño en 32 bits, así que 2³² − 1 = 4.294.967.295 bytes es el techo absoluto. Y no tiene diario: un corte de luz en mitad de una escritura puede dejarlo incoherente sin forma automática de repararlo. Sobrevive porque lo lee absolutamente todo, incluida la UEFI de tu placa, que exige una partición FAT32 para arrancar.
tmpfs no es un disco. Vive en la caché de páginas y en swap: rapidísimo y volátil. Es lo que hay detrás de /dev/shm/meteora-cache (03-03) y de /run/meteora/. Que la caché de Meteora "sea un fichero" y a la vez esté en RAM no es una contradicción: es un fichero de un sistema de archivos que no tiene dispositivo detrás. Lo veremos con detalle en 04-03.
Copia al escribir frente a diario. Son dos filosofías distintas para el mismo problema —sobrevivir a un corte de luz—. El diario anota lo que va a hacer antes de hacerlo; la copia al escribir nunca sobrescribe un bloque vivo, escribe una copia nueva y cambia el puntero al final. Es el tema de Asignación de Espacio, Journaling e Integridad.
Sumas de verificación de datos. Solo Btrfs y ZFS verifican que los datos que devuelven son los que se escribieron. ext4 y XFS verifican sus metadatos y su diario, pero si un bit de tus lecturas se corrompe en el plato, te lo entregan corrupto sin avisar. Es la corrupción silenciosa, y también es de 04-05.
La decisión de Meteora para /var/lib/meteora
Con todo lo anterior, ya se puede argumentar la elección en lugar de copiarla de un tutorial. El perfil de carga de Meteora:
| Característica de la carga | Valor |
|---|---|
| Tamaño de fichero | 17,3 MB, uno por día |
| Número de ficheros | ~365 al año, unos 1.800 en total |
| Patrón de escritura | Añadir al final, continuo, ~8 lecturas/segundo |
| Patrón de lectura | Secuencial completo (agregador) y aleatorio por mmap (meteo-api) |
| Dispositivo | RAID 1 por software sobre dos NVMe (02-05) |
| Requisito de integridad | Alto: los datos no se pueden regenerar |
| Requisito de disponibilidad | Alto: meteo-api sirve 24/7 |
Los candidatos y su descarte razonado:
| Candidato | Argumento a favor | Por qué no se elige |
|---|---|---|
| XFS | Excelente con ficheros grandes, muy paralelo, sin límite de inodos | No se puede reducir; el volumen podría necesitar ajustes |
| Btrfs | Sumas de verificación de datos, instantáneas nativas | Rendimiento irregular con escrituras continuas; su RAID 5/6 no es fiable |
| ZFS | El mejor en integridad | Fuera del núcleo; complica el mantenimiento y las actualizaciones |
| F2FS | Pensado para flash | Orientado a móviles; menos rodaje en servidor |
| ext4 | Maduro, predecible, extents, herramientas | Sin sumas de verificación de datos |
Decisión: ext4, con esta justificación:
- Madurez y previsibilidad. Es el sistema de archivos con más horas de vuelo del ecosistema Linux. Para datos irrecuperables, "aburrido y probado" vale más que "moderno y prometedor".
- Extents. Un fichero de 17 MB contiguo se describe con un solo extent en lugar de 4.219 punteros. Lo mediremos con
filefragen 04-05. - Herramientas.
dumpe2fs,debugfs,tune2fs,e2fsckyresize2fs(que sí reduce, a diferencia de XFS) forman el juego más completo. Cuando algo va mal a las tres de la mañana, eso pesa. - El diario en modo
orderedgarantiza que nunca aparecerán datos de otro fichero dentro de las lecturas tras un fallo. Lo justificaremos en 04-05. - Los inodos no son un problema en esta carga: 1.834 usados de 13 millones.
- La falta de sumas de verificación de datos se compensa por otra vía:
mdverifica el RAID 1 con un scrub semanal, y elingestorguarda un CRC32 por lectura en su propio formato.
Los parámetros exactos del formateo:
sudo mkfs.ext4 \
-b 4096 \ # bloque de 4 KiB = tamaño de página
-i 1048576 \ # un inodo por MiB: pocos ficheros y grandes
-m 1 \ # solo 1 % reservado para root (por defecto 5 %)
-L meteora-datos \ # etiqueta estable
-O extent,dir_index,has_journal,metadata_csum,64bit \
/dev/md0Qué hace cada opción y por qué aquí:
-b 4096: coincide con la página y con el sector físico del NVMe; además permitemmap()directo.-i 1048576: por defecto habría 13 millones de inodos, de los que se usan 1.834; con un inodo por MiB quedan 200.000, de sobra, y se ahorran unos 3 GiB de tabla de inodos que pasan a ser espacio útil. Es un ajuste seguro solo porque conocemos la carga.-m 1: ext4 reserva el 5 % para root, para que un disco lleno no impida iniciar sesión ni operar. En un volumen de datos de 200 GiB eso son 10 GiB inmovilizados; con el 1 % son 2 GiB, suficiente margen. Ojo: en/nunca bajes de 5 %.-O extent: extents en lugar de punteros indirectos (04-05).-O dir_index: índices hash para directorios grandes (04-02).-O metadata_csum: sumas de verificación de metadatos, que detectan corrupción del inodo o del mapa de bits.
Y así es como /var/lib/meteora/lecturas/2026-08-31.dat deja de ser una cadena mágica y pasa a ser el inodo 1180934 del ext4 etiquetado meteora-datos sobre /dev/md0.
Errores Comunes y Consejos
Creer que el ctime es la fecha de creación. Es change time: cambia con chmod, chown o al crear un enlace duro. La creación real es el crtime, que solo muestra stat en sistemas modernos. Confundirlos lleva a conclusiones falsas en cualquier análisis forense.
Interpretar mal el campo Bloques de stat. Siempre son bloques de 512 bytes, aunque el sistema use 4 KiB. Si multiplicas por 4.096 obtendrás un tamaño ocho veces mayor que el real.
No mirar df -i ante un ENOSPC. Un disco al 26 % que da "No queda espacio en el dispositivo" es casi siempre agotamiento de inodos. Comprueba siempre las dos.
Suponer que el número de inodos se puede ampliar. En ext4 se fija al formatear y no hay marcha atrás. Si prevés millones de ficheros pequeños, decide -i antes, o usa XFS o Btrfs, que los asignan dinámicamente.
Elegir un bloque grande "porque es más rápido". Con un millón de ficheros de 800 bytes, un bloque de 64 KiB desperdicia el 99 % del espacio. El tamaño de bloque depende de la distribución de tamaños de tus ficheros, no de una intuición sobre velocidad. Y en Linux no puede superar los 4 KiB de la página.
Formatear con mkfs la partición equivocada. mkfs no pregunta. Confirma siempre con lsblk y blkid antes de pulsar Intro; lo veremos en 04-03.
Consejo: guarda la salida de dumpe2fs -h de tus volúmenes. Tener a mano el UUID, el tamaño de bloque y las posiciones de los superbloques de respaldo convierte una recuperación de emergencia en un trámite de dos minutos.
Consejo: usa stat en lugar de ls -l cuando algo no cuadre. Muestra las cuatro fechas, el inodo, el dispositivo y los bloques reales. La mitad de los misterios con ficheros se resuelven leyendo un stat con calma.
Consejo: comprueba el tipo antes de asumir. Antes de cat sobre algo desconocido, mira el primer carácter de ls -l. Un cat sobre un dispositivo de bloque de 200 GiB, o sobre una FIFO sin escritor, no acaba como esperas.
Ejercicios
Ejercicio 1: identificar tipos y leer un stat
Sin usar ls -l, escribe un comando que clasifique todo lo que hay en /dev, /run y tu directorio personal por tipo de fichero, contando cuántos hay de cada uno. Después coge un fichero regular de al menos 10 MB, ejecútale stat, y responde: (a) ¿cuántos bloques de 4 KiB ocupa realmente?, (b) ¿cuánto espacio se desperdicia en el último bloque?, (c) ¿coinciden mtime y ctime, y qué significa que coincidan o que no?
Ejercicio 2: el compromiso del tamaño de bloque
Un volumen de 500 GiB va a albergar dos cargas posibles. Carga A: los ficheros diarios de Meteora, 17.280.000 bytes cada uno, durante 30 años. Carga B: 20 millones de ficheros de sesión de 600 bytes. Para tamaños de bloque de 1, 4 y 64 KiB, calcula en cada carga: bloques totales necesarios, espacio realmente ocupado, desperdicio absoluto y porcentaje. Después indica qué tamaño elegirías para cada carga y si un solo volumen puede servir para las dos.
Ejercicio 3: diagnosticar un ENOSPC engañoso
Un compañero te avisa: el servicio de sesiones de meteo-01 falla con "No queda espacio en el dispositivo", pero df -h muestra el volumen al 31 %. Escribe el procedimiento completo de diagnóstico —qué comandos ejecutas, en qué orden y qué esperas ver en cada uno—, la explicación técnica de por qué ocurre, la solución inmediata para restaurar el servicio y la solución definitiva para que no vuelva a pasar. Incluye el comando de formateo que usarías y justifica sus parámetros.
Soluciones
Solución 1
Clasificar por tipo se hace con find -type o, mejor, con el formato de stat:
for d in /dev /run "$HOME"; do
echo "=== $d ==="
find "$d" -maxdepth 1 -printf '%y\n' 2>/dev/null | sort | uniq -c | sort -rn
done-printf '%y' imprime una sola letra con el tipo (f regular, d directorio, l enlace, b, c, p, s), y sort | uniq -c los cuenta. Salida típica:
=== /dev ===
198 c ← dispositivos de carácter: terminales, /dev/null, /dev/random
42 b ← dispositivos de bloque: discos y particiones
28 d
18 l
=== /run ===
34 d
12 s ← sockets de los servicios, incluido /run/meteora/api.sock
6 p ← FIFO, incluida /run/meteora/lecturas.fifoPara las preguntas, con un stat que da Tamaño: 17280000 y Bloques: 33760:
(a) stat cuenta bloques de 512 B: 33.760 × 512 = 17.285.120 bytes. En bloques de 4 KiB son 17.285.120 / 4.096 = 4.220 bloques. Los datos necesitan ⌈17.280.000 / 4.096⌉ = 4.219, así que el bloque extra son metadatos del árbol de extents.
(b) 17.280.000 = 4.218 bloques completos + 3.072 bytes. El último bloque usa 3.072 de 4.096, así que se desperdician 1.024 bytes: el 0,006 % del fichero. Irrelevante aquí, decisivo con ficheros de 800 bytes.
(c) Si mtime y ctime coinciden, la última operación fue una escritura de contenido (que actualiza los dos). Si el ctime es posterior, después de escribir se modificó algún metadato: un chmod, un chown o un ln. Un ctime posterior al mtime sin motivo conocido es exactamente lo que hace sospechar a un analista.
Solución 2
Carga A — un fichero de 17.280.000 B, 30 años × 365 = 10.950 ficheros:
| Bloque | Bloques/fichero | Ocupado/fichero | Desperdicio/fichero | Desperdicio total |
|---|---|---|---|---|
| 1 KiB | 16.875 | 17.280.000 | 0 | 0 |
| 4 KiB | 4.219 | 17.281.024 | 1.024 | 11,2 MB |
| 64 KiB | 264 | 17.301.504 | 21.504 | 235 MB |
Sobre 189 GB de datos, incluso 235 MB es el 0,12 %. Con 4 KiB, el desperdicio es del 0,006 %: despreciable. Aquí manda el número de bloques a gestionar, y 4.219 se maneja mucho mejor que 16.875.
Carga B — 20.000.000 de ficheros de 600 B (12 GB de datos reales):
| Bloque | Ocupado/fichero | Ocupado total | Desperdicio | % desperdiciado |
|---|---|---|---|---|
| 1 KiB | 1.024 | 20,5 GB | 8,5 GB | 41 % |
| 4 KiB | 4.096 | 81,9 GB | 69,9 GB | 85 % |
| 64 KiB | 65.536 | 1.310 GB | 1.298 GB | 99,1 % |
Con 64 KiB no cabe: harían falta 1,3 TB en un volumen de 500 GiB para guardar 12 GB de datos.
Elección. Carga A: 4 KiB, por afinidad con la página y mmap(), con desperdicio nulo en la práctica. Carga B: 1 KiB, que ahorra 61 GB frente a 4 KiB. Y una advertencia importante para la carga B: 20 millones de ficheros necesitan 20 millones de inodos, y el mkfs por defecto daría 32,7 millones —justo—, así que hay que fijar -i 2048 o usar XFS.
¿Un solo volumen para las dos? Técnicamente sí, pero es mala idea: los requisitos son opuestos (bloque grande y pocos inodos frente a bloque pequeño y muchos inodos), y además mezclar cargas hace que los millones de ficheros pequeños fragmenten el espacio que necesitan los grandes. Dos volúmenes separados, que es justo el argumento del particionado que veremos en 04-03.
Solución 3
Procedimiento de diagnóstico, en orden:
df -h /var/spool/cache # 1. espacio: 31 % → no es esto
df -i /var/spool/cache # 2. inodos: 100 % → AQUÍ ESTÁ
findmnt /var/spool/cache # 3. confirmar el dispositivo y las opciones
sudo find /var/spool/cache -xdev -type f -printf '%h\n' \
| sort | uniq -c | sort -rn | head # 4. quién los ha creado
sudo dumpe2fs -h /dev/sdb1 | grep -E 'Inode count|Free inodes|Inode size'El paso 2 es el diagnóstico y el 4 identifica al culpable. -xdev es importante: sin él, find cruzaría a otros sistemas de archivos y contaría ficheros que no ocupan inodos de este volumen.
Explicación técnica. En ext4 el número de inodos es fijo y se decide al formatear, con un inodo por cada 16 KiB por defecto. Un volumen de 50 GiB tiene así 3.276.800 inodos. Cada fichero, por pequeño que sea, consume uno. Cuando se agotan, creat() y open(O_CREAT) devuelven ENOSPC —"No space left on device"— aunque queden bloques libres, porque el núcleo no distingue entre los dos recursos en el código de error. Los ficheros de sesión de 600 bytes ocupan un bloque de 4 KiB y un inodo cada uno: los inodos se agotan cuando llevas 3,2 millones, con solo 13 GB usados.
Solución inmediata (restaurar el servicio):
sudo find /var/spool/cache/sesiones -type f -mtime +7 -delete
df -i /var/spool/cache # verificar que ya hay inodos libres
sudo systemctl restart sesionesBorrar los ficheros de más de 7 días libera inodos de inmediato. Con millones de ficheros conviene find ... -delete en lugar de rm -rf, que puede desbordar la línea de comandos.
Solución definitiva, en tres capas:
- Purga automática: una unidad
systemdcon temporizador (módulo 7) o una entrada detmpfiles.dque borre las sesiones caducadas cada hora. - Reformatear con la densidad correcta, previa copia de seguridad:
-b 1024 porque los ficheros son de 600 bytes y con 4 KiB se desperdicia el 85 %; -i 2048 da un inodo por cada 2 KiB, es decir 26 millones de inodos, muy por encima de los 3,2 originales; -m 0 porque es un volumen de datos temporales donde no hace falta reserva para root.
- Vigilancia: alertar cuando
df -isupere el 80 %, exactamente igual que se vigila el espacio. Casi ningún sistema de monitorización lo hace por defecto, y por eso este fallo sigue apareciendo.
Alternativa razonable: montar /var/spool/cache como tmpfs, ya que las sesiones son volátiles por naturaleza. Se acaban los dos problemas de golpe, a cambio de RAM y de perderlas al reiniciar (04-03).
Conclusión
Un fichero es una secuencia de bytes con nombre, tamaño y propietario que el sistema coloca donde quiere y el programa lee como si fuera continua. Esa abstracción resuelve de un golpe los siete problemas que tendría cualquier aplicación trabajando sobre el vector de bloques crudo del módulo 2, y lo hace con la misma estrategia que la memoria virtual: una tabla de traducción que convierte un espacio lógico ordenado en un espacio físico disperso.
El fichero tiene tres partes en tres sitios: el contenido en la zona de datos, los metadatos en el inodo, y el nombre en el directorio. La consecuencia central, de la que cuelga medio módulo, es que el nombre no está dentro del fichero: el inodo 1180934 no sabe que se llama 2026-08-31.dat.
En UNIX hay siete tipos de fichero —regular, directorio, enlace simbólico, dispositivo de bloque, dispositivo de carácter, FIFO y socket— y los cuatro últimos ocupan inodo pero cero bloques de datos: la FIFO /run/meteora/lecturas.fifo y el socket api.sock del módulo 3 son entradas del sistema de archivos cuyo contenido vive en el núcleo. ls -l los distingue por su primer carácter y stat lo cuenta todo: tamaño lógico, bloques de 512 bytes, dispositivo, inodo, contador de enlaces y las cuatro fechas.
Físicamente, un ext4 se divide en grupos de bloques de 128 MiB, cada uno con mapa de bits de bloques, mapa de bits de inodos, tabla de inodos y zona de datos, precedidos por el superbloque —la ficha de identidad, con copias de respaldo que salvan volúmenes— y los descriptores de grupo. Pasar del número de inodo a su posición en el disco cuesta dos divisiones y una multiplicación, y esa es la razón profunda de que el inodo sea un número.
El tamaño de bloque es un compromiso medible: 4 KiB es el estándar porque coincide con la página de memoria (y por tanto con la caché de páginas y con mmap()) y con el sector físico moderno; bajarlo tiene sentido con millones de ficheros diminutos y subirlo, en Linux, ni siquiera es posible. Los inodos, en ext4, se fijan al formatear: de ahí el ENOSPC con el disco medio vacío que solo df -i explica. Y las cuatro marcas de tiempo distinguen leer (atime), modificar contenido (mtime), modificar metadatos (ctime) y crear (crtime); noatime elimina 48.000 escrituras diarias inútiles en meteo-01.
Con la comparación de familias en la mano, Meteora elige ext4 para /var/lib/meteora: madurez frente a datos irrecuperables, extents para describir 17 MB en un solo tramo, el juego de herramientas más completo para las tres de la mañana, y un ajuste consciente de -i 1048576 y -m 1 que recupera unos 11 GiB para datos útiles.
Nos queda el cabo suelto que hemos ido dejando en cada apartado: el nombre. Sabemos que no está en el inodo, sabemos que vive "en el directorio", y hemos dicho que un directorio es "un fichero especial", pero no hemos abierto ninguno. ¿Qué hay exactamente dentro de /var/lib/meteora/lecturas/? ¿Cómo consigue el sistema convertir la cadena /var/lib/meteora/lecturas/2026-08-31.dat en el número 1180934, y cuántos accesos a disco le cuesta? ¿Por qué un enlace simbólico puede quedarse roto y uno duro no? ¿Y qué pasa cuando un directorio tiene cien mil ficheros dentro?
Todo eso es lo que abre la siguiente lección: Estructuras de Directorios.
Fundamentos de Sistemas Operativos
Módulo 1: Introducción a los Sistemas Operativos
- Conceptos Básicos de Sistemas Operativos
- Historia y Evolución de los Sistemas Operativos
- Tipos de Sistemas Operativos
- Funciones Principales de un Sistema Operativo
- Arquitectura del Núcleo: Monolítico, Microkernel e Híbrido
- Modo Usuario, Modo Núcleo y Llamadas al Sistema
Módulo 2: Gestión de Recursos
- Gestión de Procesos
- Planificación de la CPU
- Gestión de Memoria
- Memoria Virtual y Paginación
- Gestión de Almacenamiento
- Gestión de Dispositivos
- Controladores, Interrupciones y Operaciones de E/S
Módulo 3: Concurrencia
- Conceptos de Concurrencia
- Hilos y Procesos
- Comunicación entre Procesos (IPC)
- Sincronización y Exclusión Mutua
- Problemas Clásicos de Concurrencia
- Interbloqueos: Prevención, Detección y Recuperación
Módulo 4: Estructuras de Archivos
- Sistemas de Archivos
- Estructuras de Directorios
- Particiones, Montaje y Sistema de Archivos Virtual
- Gestión de Archivos
- Asignación de Espacio, Journaling e Integridad
- Seguridad y Permisos de Archivos
Módulo 5: Protección y Seguridad del Sistema
- Principios de Protección y Control de Acceso
- Usuarios, Autenticación y Escalada de Privilegios
- Amenazas Comunes y Endurecimiento del Sistema
- Auditoría, Registros y Respuesta a Incidentes
Módulo 6: Virtualización y Contenedores
- Virtualización: Hipervisores y Máquinas Virtuales
- Contenedores: Namespaces y cgroups
- El Sistema Operativo en la Nube
- Sistemas Operativos Móviles y de Tiempo Real
